Skip to content

fix(ci): stop the benchmark suite starving CI and publishing partial numbers - #350

Merged
marius-bughiu merged 4 commits into
mainfrom
fix/issue-335-benchmark-ci-integrity
Aug 7, 2026
Merged

fix(ci): stop the benchmark suite starving CI and publishing partial numbers#350
marius-bughiu merged 4 commits into
mainfrom
fix/issue-335-benchmark-ci-integrity

Conversation

@marius-bughiu

Copy link
Copy Markdown
Owner

Three open issues on milestone 2.4.0 — #319, #335 and #300 — turned out to be one lane: nothing rationed the most expensive workflow in the repository, and the failures compounded. Fixing them separately would have meant three PRs touching the same forty lines of benchmarks.yml, so they ship together.

What was wrong

Runs accumulated (#319). benchmarks.yml declared no concurrency group, so every push to a PR branch started another full 8-shard run and none of the superseded ones were cancelled. Five pushes over one review loop created five live runs — up to 24 runner slots — and left CI and Coverage, the checks that actually gate correctness, queued for ~50 minutes behind perf numbers nobody would read. Only the newest run's numbers are ever read, so the rest was pure waste.

Runs overlapped (#335). With three branches' runs in flight, every shard measured 1.75–2.0× its baseline and one hit the timeout-minutes: 120 cap — on two pull requests whose diffs were XML doc comments only. The loud failure is a cancelled shard; the quiet one is worse, because a shard that completes under uneven contention still publishes its skewed delta to the dashboard, and the same-runner A/B invariant only cancels hardware when both sides see the same neighbour load.

The two sides of the A/B packed from different class lists (#300). Shard membership comes from greedy bin-packing over the benchmark class list, and the PR head has a class main does not. So shard i was not the same slice on the two sides, a job could draw a light head slice and a heavy base slice, and the pair overran its budget even when every individual slice was well inside it. This recurs for every PR that introduces a benchmark class — which is every new collection, the repo's most common feature shape.

What changed

1. The workflow supersedes its own run — .github/workflows/benchmarks.yml

concurrency:
  group: benchmarks-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

One group expression, two behaviours. On a PR the key is the PR number, so a push cancels the previous run. On main the key is the commit SHA, so every commit is its own group and cancel-in-progress can never discard one — each commit's numbers are independently meaningful there, and a cancelled run would leave a hole in the gh-pages time series.

2. The suite does not run when the diff cannot move a number — scripts/benchmark_relevant_changes.js

paths: src/** is a path filter, not a semantic one: an XML doc-comment edit is a src/** change and buys a full sharded A/B run for a diff with zero IL in it. The new gate is one-directional — skipping is only claimed when every changed path is one of:

  1. outside src/ (docs, the dashboard, the changelog);
  2. inside a project Celerity.Benchmarks.csproj does not reference — Celerity.Tests, Celerity.Fuzz, Celerity.AotSmokeTest, so nothing in them can reach a measurement;
  3. a modified .cs file whose text is unchanged once comments are stripped.

Everything else runs: an added or deleted file, a rename, a non-.cs file under src/, the workflow itself, this script, a failing git command, a missing argument. And it is applied to the pull-request path onlymain always measures, so a wrongly-skipped PR is still measured on merge. That caps the worst case of a gate mistake at "the PR comment was missing", never "the regression was never seen".

Comment-stripping is a real C# scanner with a mode stack, not a //-prefix test: // occurs inside literals, and the verbatim / interpolated / raw / interpolated-raw forms desynchronise a guess. --self-test pins 23 cases (escaped quotes, @"a ""//"" b", $"{dict["k"]}", $$"""{{x}} // text""", '\'', @class) and runs in a new benchmark-gate job in ci.yml.

Verified against the actual history, not just unit-tested:

commit verdict
#330 merge (doc-only, named in #335) run=false
#331 merge (doc-only, named in #335) run=false
e94db0d feat: add SegmentTree run=true
5647031 fix(PartialSort): TopK alias guard run=true
d646716 docs(SegmentTree) — comment + md only run=false
this PR run=true

Both PRs that caused the #335 incident would have been skipped entirely.

What I deliberately did not do. #335's option 1 was a global concurrency: { group: benchmarks, cancel-in-progress: false } to serialize the workflow. GitHub queues at most one pending run per group and cancels the older pending one, so global serialization would silently drop runs — a worse failure than slow feedback, and it defeats the point of measuring. What ships is the issue's option 2, which it rated "the cheapest win and independently worthwhile" and preferred doing first. Option 3 (raise the timeout) treats the symptom; the issue says so itself.

3. Shard i is the same slice on both sides — src/Celerity.Benchmarks/Program.cs

The base replays the class list the head resolved (--shard-classes) instead of packing its own (--shard-classes-out writes it). That makes the base a subset of the head by construction, so the pair is bounded by twice the head slice — the quantity the packer already balances — and shard i compares like with like. A class the PR adds is simply absent from the base's suite; the process says so and skips it, and the comparison reports it as 🆕 new rather than as a delta. This is the issue's option 1, chosen over option 3 (raise the timeout), which only moves the ceiling.

--shard-dry-run resolves a shard's class list and stops. The packing was previously observable only by running the suite for hours, which is a large part of why the head/base mismatch went unnoticed.

4. A partial report is loud — option 4 of #300

The aggregate job runs with if: always(), so a cancelled shard produced a report that was legitimately missing whole benchmark classes and read exactly like a complete one. The merge step now names the missing shard indices, emits a ::warning:: annotation, and the PR comment leads with a > [!WARNING] block above the fold before any numbers.

Parity

This is CI/infrastructure work with no new collection, public API or hasher, so most of the collection parity checklist does not apply — there is no dedicated collection test file, no cross-collection shared-test row, no new XxxBenchmark class, no COLLECTIONS dashboard entry and no docs/api/collections.md section to add. What does apply:

  • Tests--self-test on the new script, wired into a benchmark-gate job in ci.yml, mirroring how check_doc_anchors.js is guarded.
  • DocsCONTRIBUTING.md (three new bullets under CI: it supersedes itself, it is skipped on inert diffs, shard i means the same slice), docs/testing.md (the workflow table row), docs/performance.md (the core-suite description).
  • CHANGELOG — two ### Added and three ### Fixed bullets.
  • ROADMAP — a done entry under 2.4.0's "Build- and release-pipeline integrity" group recording all three issues and the three design calls above.

Test plan

  • dotnet build — 0 errors (3582 pre-existing warnings, tracked in Test project emits 3264 build warnings, burying 20 real CS8631 nullability warnings #332).
  • dotnet test5604 passed / 0 failed in Celerity.Tests, plus 46 / 30 / 37 in the Ring / Sentinel / Cardinality test projects. 5717 total, all green.
  • node scripts/benchmark_relevant_changes.js --self-test — 23 lexer cases pinned.
  • node scripts/check_doc_anchors.js — 564 links across 23 files resolve.
  • node scripts/check_dashboard_coverage.js — 155 cards across 47 collections wired.
  • Both workflow files parse as YAML; the embedded github-script body passes node --check; every multi-line run: step passes bash -n.
  • --shard-dry-run over shards 0/1/3/7 and the --shard-classes replay path, including a roster naming a class the replaying side does not have (reported and skipped, no crash).
  • Gate verdicts checked against six real commits including the two PRs Benchmark shards run ~2x slower when PRs overlap, hitting the 120-min timeout on doc-only changes #335 names (table above).
  • CI matrix (Linux / Windows / macOS × net8.0 / net9.0 / net10.0), coverage gate, AOT publish — on this PR.
  • The benchmark workflow itself is the thing under test here. This PR's gate verdict is run=true, so the full 8-shard matrix runs and exercises the new head/base roster handoff end-to-end. Worth watching that the base step logs the replayed slice and that no shard is cancelled.
  • gh-pages dashboard refresh on merge to main — the publish path is unchanged, but the main-push run should still produce a complete report and refresh https://marius-bughiu.github.io/Celerity/dev/bench/.

Closes #319. Closes #335. Closes #300.

…numbers

Three open issues on 2.4.0 turned out to be one lane: nothing rationed the
most expensive workflow in the repository.

Runs accumulated. benchmarks.yml declared no concurrency group, so five
pushes over one review loop created five uncancelled eight-shard runs and
left CI and Coverage queued for ~50 minutes behind numbers nobody would
read. The workflow now supersedes its own in-flight run, keyed on the PR
number; the main path is keyed on the commit SHA instead, so every commit
is its own group, cancel-in-progress can never discard one, and the
published series keeps every point. Closes #319.

Runs overlapped. With three branches in flight every shard measured
1.75-2.0x its baseline and one hit the 120-minute cap - on two pull
requests whose diffs were XML doc comments only. The quiet failure is the
worse one: a shard that finishes under uneven contention still publishes
its skewed delta. scripts/benchmark_relevant_changes.js now gates the PR
path and does not run the suite when the diff cannot move a number. It is
one-directional by construction (only documentation, the three projects
Celerity.Benchmarks.csproj does not reference, and .cs files whose text is
unchanged once comments are stripped can be skipped) and never applies to
main, so a gate mistake costs a missing PR comment rather than an unseen
regression. It correctly skips both pull requests the issue names and runs
on every code change it was tested against.

The issue's own first choice - a global serialize-everything concurrency
group - was deliberately not taken: GitHub queues at most one pending run
per group and cancels the older pending one, so serializing would silently
drop runs. What ships is its option 2, which it rated cheapest and most
obviously correct. Closes #335.

The two sides of the A/B packed from different class lists. Greedy
bin-packing is a function of the whole list and the PR head has a class
main does not, so shard i was not the same slice on both sides and could
pair a light head slice with a heavy base one. The base now replays the
class list the head resolved, which makes it a subset of the head by
construction: the pair is bounded by twice the head slice, the quantity
the packer already balances. Option 4 of that issue ships alongside - a
report missing a shard says so above the fold, since a partial comparison
previously read exactly like a complete one. Closes #300.

The comment-stripping rests on a real C# scanner rather than a //-prefix
test, because // occurs inside literals and the verbatim / interpolated /
raw forms desynchronise a guess; a --self-test pins it in a new
benchmark-gate job. --shard-dry-run resolves a shard's class list without
measuring, so the packing is inspectable without a multi-hour run.
Copilot AI lite review requested due to automatic review settings August 7, 2026 01:24
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Coverage

Metric Value
Line 100% (12634/12634)
Branch 100% (5188/5188)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the repository’s benchmark CI pipeline so it no longer starves other workflows, avoids running on diffs that cannot affect measured performance, and prevents publishing “quietly partial” benchmark comparisons.

Changes:

  • Add workflow-level concurrency and a PR-only relevance gate to avoid stacked/overlapping benchmark runs and to skip inert diffs.
  • Make benchmark shard membership consistent between PR head/base by replaying the head’s resolved class roster, and add an explicit “incomplete report” warning path.
  • Update contributor/docs/changelog/roadmap documentation to reflect the new CI behavior and operational expectations.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Celerity.Benchmarks/Program.cs Adds shard roster recording/replay and a dry-run mode so head/base compare the same slice and packing can be inspected without running benchmarks.
scripts/benchmark_relevant_changes.js New gate script to decide whether a PR diff can affect benchmark numbers (comment-only, docs-only, or unreferenced-project changes can skip).
ROADMAP.md Records the milestone “done” item summarizing the three related benchmark CI issues and the chosen design decisions.
docs/testing.md Updates the workflow table to document benchmark run superseding + skip behavior on inert PR diffs.
docs/performance.md Clarifies that the lean CI suite runs only when the PR can move numbers (while main always measures).
CONTRIBUTING.md Documents benchmark CI behavior (superseding, relevance gate, and shard slice parity) for contributors.
CHANGELOG.md Notes the new benchmark relevance gate and shard dry-run, and documents fixes for benchmark CI starvation/timeouts/partial reports.
.github/workflows/ci.yml Adds a lightweight benchmark-gate job to pin the gate script’s lexer via --self-test.
.github/workflows/benchmarks.yml Adds concurrency, introduces the relevance-gate job, replays shard class rosters for base runs, and makes partial reports loud (warnings + PR comment banner).

Comment thread scripts/benchmark_relevant_changes.js Outdated
Comment thread scripts/benchmark_relevant_changes.js
Both from the Copilot review, both correct.

The unbenchmarked-project list named only three of the six projects the
benchmark process cannot load, so a change confined to Celerity.Ring.Tests,
Celerity.Sentinel.Tests or Celerity.Cardinality.Tests still bought a full
sharded run. Rather than append three more strings to a list that had
already drifted once, the rule is now stated as the reachable set
(BENCHMARKED_PROJECTS, following Celerity.Benchmarks.csproj transitively)
plus a convention for the rest, and --self-test refuses to pass while any
project directory under src/ is classified by neither. A project that fits
no rule is still treated as significant, so the drift guard fails loudly
without ever making the gate less safe.

normalize() trimmed every line after comment-stripping, which is right for
code and wrong inside a multi-line verbatim or raw literal, where the
indentation and the blank lines are part of the string value and reach the
IL. Reindenting such a literal therefore read as "comments only". A newline
inside a string frame is now emitted as a sentinel instead, so each literal
occupies one logical line and the per-line trim can only touch the code
around it. Pinned both ways: reindenting a literal must not normalize
identically, and a comment edit beside one must.

Also batched from my own re-read: the relevance-gate job no longer does a
full-history checkout on the push path, where it answers without consulting
the repository at all and the clone was pure latency ahead of the matrix;
and the gate's git invocations set core.quotePath=false so a path with
non-ASCII characters is compared exactly rather than taking the fail-safe
run path.

Historical verdicts are unchanged: the two documentation-only pull requests
still skip and every code change still runs.
Copilot AI review requested due to automatic review settings August 7, 2026 01:36
@marius-bughiu

Copy link
Copy Markdown
Owner Author

The concurrency fix verified itself on this PR

Pushing 5ee872d (the review fixes) superseded the run for 71a30ae, and GitHub cancelled it automatically:

2026-08-07T01:36:20Z  5ee872d  in_progress
2026-08-07T01:24:28Z  71a30ae  completed/cancelled

On main today that second run would have kept up to eight runners busy for hours measuring a commit nobody would ever read the numbers for — which is exactly the accumulation #319 describes, reproduced and then fixed inside a single PR.

The relevance gate also ran on both pushes and reported run=true both times, with the same per-path reasoning as locally, so the fast-path and the gate are both exercised here rather than only asserted.

What is still outstanding on this PR is the part that can only be proven by letting it finish: the 8-shard matrix on 5ee872d is measuring the head slice now, and the base step afterwards is the first real exercise of the --shard-classes roster handoff (#300). Worth a glance at any shard's Run base (main) benchmarks step log for the replayed slice before merging.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/Celerity.Benchmarks/Program.cs:209

  • --shard-classes is documented as replaying the head slice, but the current implementation reads the file into a HashSet<string>, which drops ordering (and duplicates). That means the base side won’t actually replay the slice verbatim, and the run order can differ from the head’s packed order.

Preserve the file’s line order when rebuilding slice (and emit missing-class messages per line) so replay is deterministic and truly matches what the head resolved.

            var wanted = new HashSet<string>(
                File.ReadAllLines(replayPath)
                    .Select(line => line.Trim())
                    .Where(line => line.Length > 0),
                StringComparer.Ordinal);

CHANGELOG.md:32

  • This changelog entry is much longer than the project’s documented convention (“keep each entry short and user-facing — a few sentences at most”; see CONTRIBUTING.md:181). Consider tightening it to the observable behavior change and why it matters, and keep the detailed incident narrative in the PR body instead.
- Pushing to a pull request no longer stacks another eight-runner benchmark matrix behind the last — the workflow supersedes its own in-flight run. Five pushes over one review loop had left `CI` and `Coverage`, the checks that actually gate correctness, queued for ~50 minutes behind perf numbers nobody would read. Pushes to `main` are keyed per commit instead, so none is ever cancelled and the published history keeps every point. Closes [#319](https://github.com/marius-bughiu/Celerity/issues/319).

…entries

Both from the second Copilot review, which reported "no new comments" and
then carried two in a suppressed block.

--shard-classes read the roster into a HashSet and filtered the suite by it,
so the base ran the right classes in the wrong order: declaration order
rather than the packed order the head wrote. The set is what bounds the job,
so this was not the timeout bug, but running the two sides in different
orders reintroduces in miniature the systematic head/base difference the
whole handoff exists to remove. The roster is now walked in file order,
de-duplicated on the way, and a name this side does not have is reported
where it appears rather than in a separate sorted pass. Verified: head shard
1 and its replay now resolve to the identical sequence, where before the
replay came back reordered.

The changelog entries ran to the incident narrative that CONTRIBUTING.md
says belongs in the PR body — a release-safety rule here, not only style,
since the release workflow extracts a whole version section verbatim as the
GitHub release body. Five entries condensed to what observably changed and
why it matters; the narrative is already in the PR description.
Copilot AI review requested due to automatic review settings August 7, 2026 01:42
@marius-bughiu

Copy link
Copy Markdown
Owner Author

Re: the second review's two suppressed comments

Both were right and both are fixed in 9aa3672. Answering here since suppressed comments have no thread to reply on.

1. --shard-classes dropped the head's ordering (Program.cs:209).

Correct, and I had missed it. The implementation read the roster into a HashSet<string> and then filtered CoreBenchmarks by it, so the base ran the right set in declaration order rather than the packed order the head wrote. Demonstrated before the fix:

head shard 0:  StringHasherBenchmark, FrozenCeleritySetBenchmark, FenwickTreeBenchmark
base replay:   FrozenCeleritySetBenchmark, FenwickTreeBenchmark, StringHasherBenchmark

The set is what bounds the job, so this was not the timeout bug — but running the two sides in different orders reintroduces, in miniature, exactly the systematic head/base difference the roster handoff exists to remove. Not something I want in a same-runner A/B.

The roster is now walked in file order into a List<Type>, de-duplicated as it goes (your parenthetical about duplicates), with a missing class reported at the point it appears rather than in a separate sorted pass. After the fix head shard 1 and its replay resolve to the identical sequence, and a roster with a duplicate, an unknown class and padded whitespace resolves correctly:

BitSetBenchmark / BrandNewBenchmark / BitSetBenchmark / (blank) / "  LruCacheBenchmark  "
  -> Shard class 'BrandNewBenchmark' is not in this side's core suite — skipping it.
  -> Shard resolves to 2 class(es): BitSetBenchmark, LruCacheBenchmark

2. The changelog entries were too long (CHANGELOG.md:32).

Also correct, and it is the rule I should have applied — CONTRIBUTING.md is explicit that this is a release-safety rule rather than a style preference, since release.yml extracts a whole version section verbatim as the GitHub release body and the repo has previously hit that ceiling. I had written the incident narrative ("five pushes over one review loop…") into the entry, which is precisely what it says to leave in the PR body.

All five entries are condensed to the observable change and why it matters; the narrative stays in the PR description above. The [Unreleased] section is now 8,159 characters.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

… measurement

The first full run of this workflow found a real defect in it, which no
amount of local testing could have: every shard was cancelled at the
120-minute cap.

The base step builds a worktree at the `main` tip and runs THAT code, so it
only understands flags already on `main`. Switching the base from --shard to
--shard-classes meant a base that predates the flag matched nothing, fell
through to the whole suite, and ran until the job timeout: shard 0's head
measured 3 classes and 97 benchmarks in 66 minutes, then the base logged
"Found 12 benchmarks" nine times over in 53 minutes before being killed. This
is the same transitional trap the comment I replaced had been warning about
for --shard itself. Both selectors are now passed, so the base packs its own
slice until this merges and replays the head's afterwards, and the constraint
is written down where the next selector will be added.

The run also measured what the cap should be. The eight head slices took
45.8, 48.7, 55.4, 55.5, 56.8, 58.2, 63.9 and 67.3 minutes; the base replays
the head's slice, so a job costs about twice its head slice, and shards 0 and
2 exceed 120 minutes on their own. The cap was set when the suite was smaller
and Sorting, SortedSpan and SegmentTree have each added classes since, so
120 -> 180 is sizing the budget to the bound rather than buying room for an
imbalance -- the imbalance is what the roster handoff fixes, and it had to
exist first for this number to mean anything.

Widening the matrix was the alternative and is rejected in the comment: the
81-case StringHasherBenchmark is one class and sharding is by class, so it
floors the heaviest slice however many shards there are, and more shards
means more concurrent runners -- the contention this change exists to reduce.
If slices reach 90 minutes the fix is to split that class, not to raise this
again.

Verified locally that the new code still prefers the roster when both flags
are present: with --shard 5 and shard 0's roster it resolves to shard 0's
three classes in order, where --shard 5 alone packs a different seven.
Copilot AI review requested due to automatic review settings August 7, 2026 03:49
@marius-bughiu

Copy link
Copy Markdown
Owner Author

The first full run found a real bug in this PR — fixed in f06f4b1

Letting the 8-shard matrix run to completion was worth it: every shard was cancelled at the 120-minute cap, and the cause was a defect I introduced.

What went wrong. The base step builds a worktree at the main tip and runs that code. main does not have --shard-classes yet, so switching the base to it meant the base matched nothing, fell through to the full suite, and ran until the job timeout. From shard 0's log:

01:44:14  Wrote 3 shard class name(s) to /tmp/head-shard-classes.txt
01:44:43  // Found 81 benchmarks:          <- head, shard 0 slice
02:50:47  Global total time: 01:06:31, executed benchmarks: 97
02:50:47  Benchmarking base (main) at 89026ce, shard 0
02:51:41  // Found 12 benchmarks:          <- base, and again, and again...
03:41:27  // Found 12 benchmarks:              (9+ classes, i.e. the whole suite)
03:43:35  [cancelled]

This is the same transitional trap the comment I replaced had been warning about for --shard itself — I deleted the warning and then walked into it. Both selectors are now passed: the base packs its own slice until this merges, and replays the head's roster afterwards. The constraint is now written down at the call site, so the next selector gets added the same way.

The run also measured what the timeout should be, which is the part I could not have known when I argued against #300's option 3. Head slices on this run:

shard 4 6 7 1 3 5 2 0
head (min) 45.8 48.7 55.4 55.5 56.8 58.2 63.9 67.3
≈ job (2×) 91.6 97.4 110.8 110.9 113.5 116.4 127.7 134.6

Because the base replays the head's slice, a job costs about twice its head slice — and shards 0 and 2 exceed 120 minutes on their own, with the imbalance already fixed. The cap dates from a smaller suite; Celerity.Sorting, SortedSpan and SegmentTree have each added classes since. So 120 → 180 here is sizing the budget to the measured bound rather than papering over an imbalance, and it only means anything because the roster handoff established that bound first.

I rejected widening the matrix instead, and said why in the comment: the 81-case StringHasherBenchmark is a single class and sharding is by class, so it floors the heaviest slice however many shards there are — and more shards means more concurrent runners, which is the contention #335 and #319 are about. If slices reach ~90 min the fix is to split that class, not to raise this again.

One thing worth calling out as a positive: aggregate & report behaved exactly as intended under total shard loss — it ran, found no head reports, said so, and exited cleanly rather than failing or publishing a silently empty comparison. That is the #300 option-4 path doing its job on its first real exercise.

Verified locally that precedence is right when both flags are present: --shard 5 plus shard 0's roster resolves to shard 0's three classes in order, where --shard 5 alone packs a different seven.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Benchmarks

8 regressions ⚠️ vs main, 5 improvements ✅ (rows past ±10% beyond noise).

Highlights

Benchmark This PR StdDev main Δ
PooledCelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 5.37 μs 525.2 ns 4.71 μs +14.1% ⚠️
SwissDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.73 μs 118.0 ns 6.18 μs -23.5% ✅
SwissDictionaryBenchmark.SwissDictionary_Lookup(ItemCount: 1000) 3.24 μs 252.6 ns 2.88 μs +12.5% ⚠️
SortedSpanBenchmark.Linq_UnionLinq(ItemCount: 100000) 5.24 ms 292.13 μs 6.18 ms -15.2% ✅
SmallDictionaryBenchmark.SmallDictionary_Remove(ItemCount: 8) 1.11 μs 112.8 ns 1.52 μs -26.7% ✅
SmallDictionaryBenchmark.Dictionary_Remove(ItemCount: 64) 6.47 μs 219.1 ns 4.86 μs +33.1% ⚠️
RobinHoodDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 12.78 μs 134.9 ns 14.07 μs -9.2% ✅
CompressedIntSetBenchmark.HashSet_Union(ItemCount: 1000) 34.16 μs 4.39 μs 27.52 μs +24.1% ⚠️
CelerityMultiMapBenchmark.Dictionary_Lookup(ItemCount: 1000) 3.73 μs 198.9 ns 3.36 μs +11.0% ⚠️
CelerityMultiMapBenchmark.Dictionary_Remove(ItemCount: 1000) 20.91 μs 1.44 μs 32.88 μs -36.4% ✅
TopKSketchBenchmark.Dictionary_TopK(ItemCount: 1000) 31.1 ns 1.7 ns 28.0 ns +11.3% ⚠️
TrieBenchmark.Trie_PrefixMatch(ItemCount: 100000) 8.33 ms 1.17 ms 6.12 ms +36.2% ⚠️
TrieBenchmark.Trie_SpanLookup(ItemCount: 100000) 10.91 ms 100.25 μs 9.78 ms +11.6% ⚠️
Collections (646)
Benchmark This PR StdDev main Δ
FrozenCeleritySetBenchmark.FrozenSet_Build(ItemCount: 1000) 146.78 μs 782.9 ns 146.03 μs +0.5%
FrozenCeleritySetBenchmark.FrozenCeleritySet_Build(ItemCount: 1000) 3.36 ms 53.82 μs 3.41 ms -1.5%
FrozenCeleritySetBenchmark.FrozenSet_Build(ItemCount: 100000) 25.83 ms 366.39 μs 26.85 ms -3.8%
FrozenCeleritySetBenchmark.FrozenCeleritySet_Build(ItemCount: 100000) 1.41 s 46.40 ms 1.40 s +0.2%
FrozenCeleritySetBenchmark.FrozenSet_Contains(ItemCount: 1000) 5.67 μs 13.2 ns 5.68 μs -0.0%
FrozenCeleritySetBenchmark.FrozenCeleritySet_Contains(ItemCount: 1000) 83.09 μs 1.18 μs 83.11 μs -0.0%
FrozenCeleritySetBenchmark.FrozenSet_Contains(ItemCount: 100000) 2.03 ms 49.15 μs 2.07 ms -2.2%
FrozenCeleritySetBenchmark.FrozenCeleritySet_Contains(ItemCount: 100000) 7.99 ms 74.65 μs 7.98 ms +0.2%
FenwickTreeBenchmark.Array_Mixed(ItemCount: 1000) 216.54 μs 234.5 ns 216.60 μs -0.0%
FenwickTreeBenchmark.FenwickTree_Mixed(ItemCount: 1000) 9.52 μs 271.9 ns 9.69 μs -1.8%
FenwickTreeBenchmark.Array_Mixed(ItemCount: 100000) 205.38 ms 752.17 μs 204.74 ms +0.3%
FenwickTreeBenchmark.FenwickTree_Mixed(ItemCount: 100000) 561.29 μs 14.85 μs 561.22 μs +0.0%
FenwickTreeBenchmark.Array_RangeSum(ItemCount: 1000) 163.66 μs 886.6 ns 164.02 μs -0.2%
FenwickTreeBenchmark.FenwickTree_RangeSum(ItemCount: 1000) 5.99 μs 128.2 ns 6.00 μs -0.3%
FenwickTreeBenchmark.Array_RangeSum(ItemCount: 100000) 146.89 ms 2.81 ms 144.88 ms +1.4%
FenwickTreeBenchmark.FenwickTree_RangeSum(ItemCount: 100000) 286.56 μs 409.4 ns 287.41 μs -0.3%
CeleritySetBenchmark.HashSet_Add(ItemCount: 1000) 12.44 μs 35.5 ns 12.41 μs +0.2%
CountMinSketchBenchmark.Dictionary_Add(ItemCount: 1000) 10.34 μs 52.1 ns 10.32 μs +0.1%
CeleritySetBenchmark.CeleritySet_Add(ItemCount: 1000) 9.24 μs 97.7 ns 9.54 μs -3.2%
CountMinSketchBenchmark.CountMinSketch_Add(ItemCount: 1000) 13.05 μs 167.1 ns 12.98 μs +0.6%
CeleritySetBenchmark.HashSet_Add(ItemCount: 100000) 5.23 ms 99.35 μs 5.20 ms +0.7%
CountMinSketchBenchmark.Dictionary_Add(ItemCount: 100000) 1.45 ms 8.06 μs 1.46 ms -0.3%
CeleritySetBenchmark.CeleritySet_Add(ItemCount: 100000) 3.47 ms 12.28 μs 3.63 ms -4.6%
CountMinSketchBenchmark.CountMinSketch_Add(ItemCount: 100000) 1.13 ms 6.19 μs 1.14 ms -0.6%
BitSetBenchmark.BitArray_And(ItemCount: 1024) 96.8 ns 4.0 ns 93.8 ns +3.2%
BitSetBenchmark.BitSet_And(ItemCount: 1024) 1.23 μs 2.6 ns 1.23 μs -0.2%
BitSetBenchmark.BitArray_And(ItemCount: 1000000) 44.86 μs 575.0 ns 45.60 μs -1.6%
BitSetBenchmark.BitSet_And(ItemCount: 1000000) 5.03 ms 5.87 μs 5.04 ms -0.0%
CeleritySetBenchmark.HashSet_Contains(ItemCount: 1000) 4.71 μs 12.7 ns 4.71 μs +0.1%
CeleritySetBenchmark.CeleritySet_Contains(ItemCount: 1000) 2.05 μs 53.6 ns 1.99 μs +3.0%
CeleritySetBenchmark.HashSet_Contains(ItemCount: 100000) 1.55 ms 32.52 μs 1.51 ms +2.0%
CeleritySetBenchmark.CeleritySet_Contains(ItemCount: 100000) 521.77 μs 10.95 μs 505.86 μs +3.1%
CountMinSketchBenchmark.Dictionary_Estimate(ItemCount: 1000) 4.66 μs 6.2 ns 4.69 μs -0.5%
CountMinSketchBenchmark.CountMinSketch_Estimate(ItemCount: 1000) 8.50 μs 24.1 ns 8.49 μs +0.1%
CountMinSketchBenchmark.Dictionary_Estimate(ItemCount: 100000) 564.72 μs 34.61 μs 531.89 μs +6.2%
CountMinSketchBenchmark.CountMinSketch_Estimate(ItemCount: 100000) 2.34 ms 2.21 μs 2.34 ms +0.1%
LruCacheBenchmark.Dictionary_Get(ItemCount: 1000) 24.35 μs 397.7 ns 24.04 μs +1.3%
LruCacheBenchmark.LruCache_Get(ItemCount: 1000) 7.40 μs 40.4 ns 7.36 μs +0.5%
LruCacheBenchmark.Dictionary_Get(ItemCount: 100000) 24.69 μs 262.8 ns 25.58 μs -3.5%
LruCacheBenchmark.LruCache_Get(ItemCount: 100000) 7.52 μs 17.8 ns 7.58 μs -0.8%
LruCacheBenchmark.Dictionary_GetMissing(ItemCount: 1000) 4.59 μs 3.2 ns 4.61 μs -0.5%
LruCacheBenchmark.LruCache_GetMissing(ItemCount: 1000) 3.68 μs 2.9 ns 3.68 μs -0.1%
LruCacheBenchmark.Dictionary_GetMissing(ItemCount: 100000) 536.21 μs 3.83 μs 537.65 μs -0.3%
LruCacheBenchmark.LruCache_GetMissing(ItemCount: 100000) 1.52 ms 525.5 ns 1.52 ms +0.0%
PooledCelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.18 μs 53.6 ns 13.12 μs +0.5%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Insert(ItemCount: 1000) 8.40 μs 148.7 ns 8.40 μs -0.1%
PooledCelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 5.14 ms 57.86 μs 5.15 ms -0.2%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Insert(ItemCount: 100000) 3.33 ms 18.01 μs 3.33 ms -0.2%
PooledCelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 5.37 μs 525.2 ns 4.71 μs +14.1% ⚠️
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Lookup(ItemCount: 1000) 2.53 μs 12.4 ns 2.50 μs +1.1%
PooledCelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.61 ms 2.64 μs 1.61 ms +0.1%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Lookup(ItemCount: 100000) 785.74 μs 43.78 μs 814.66 μs -3.6%
BitSetBenchmark.BitArray_Or(ItemCount: 1024) 88.0 ns 6.8 ns 93.9 ns -6.2%
BitSetBenchmark.BitSet_Or(ItemCount: 1024) 1.23 μs 2.5 ns 1.23 μs -0.1%
BitSetBenchmark.BitArray_Or(ItemCount: 1000000) 45.80 μs 250.8 ns 45.56 μs +0.5%
BitSetBenchmark.BitSet_Or(ItemCount: 1000000) 5.04 ms 7.51 μs 5.04 ms -0.1%
BitSetBenchmark.BitArray_PopCount(ItemCount: 1024) 1.30 μs 68.7 ns 1.30 μs +0.1%
BitSetBenchmark.BitSet_PopCount(ItemCount: 1024) 6.9 ns 0.0 ns 6.9 ns -0.5%
BitSetBenchmark.BitArray_PopCount(ItemCount: 1000000) 5.48 ms 2.32 μs 5.48 ms +0.0%
BitSetBenchmark.BitSet_PopCount(ItemCount: 1000000) 5.55 μs 5.4 ns 5.55 μs -0.0%
LruCacheBenchmark.Dictionary_Put(ItemCount: 1000) 88.76 μs 1.88 μs 89.40 μs -0.7%
LruCacheBenchmark.LruCache_Put(ItemCount: 1000) 401.99 μs 17.70 μs 405.66 μs -0.9%
LruCacheBenchmark.Dictionary_Put(ItemCount: 100000) 7.67 ms 55.45 μs 7.74 ms -0.9%
LruCacheBenchmark.LruCache_Put(ItemCount: 100000) 6.57 ms 29.31 μs 6.56 ms +0.2%
CeleritySetBenchmark.HashSet_Remove(ItemCount: 1000) 25.66 μs 1.74 μs 29.34 μs -12.5%
PooledCelerityDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 76.62 μs 6.86 μs 78.90 μs -2.9%
CeleritySetBenchmark.CeleritySet_Remove(ItemCount: 1000) 113.97 μs 8.34 μs 115.59 μs -1.4%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Remove(ItemCount: 1000) 120.12 μs 7.24 μs 125.89 μs -4.6%
CeleritySetBenchmark.HashSet_Remove(ItemCount: 100000) 1.68 ms 13.19 μs 1.68 ms +0.0%
PooledCelerityDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.00 ms 26.17 μs 2.01 ms -0.4%
CeleritySetBenchmark.CeleritySet_Remove(ItemCount: 100000) 1.48 ms 18.69 μs 1.48 ms -0.2%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Remove(ItemCount: 100000) 1.70 ms 16.62 μs 1.70 ms -0.3%
PartialSortBenchmark.Array_Select(ItemCount: 100) 476.1 ns 4.4 ns 476.2 ns -0.0%
PartialSortBenchmark.PartialSort_Select(ItemCount: 100) 351.2 ns 20.6 ns 328.8 ns +6.8%
PartialSortBenchmark.Array_Select(ItemCount: 1000) 10.30 μs 128.0 ns 10.30 μs +0.0%
PartialSortBenchmark.PartialSort_Select(ItemCount: 1000) 5.22 μs 468.0 ns 5.67 μs -8.0%
PartialSortBenchmark.Array_Select(ItemCount: 100000) 6.54 ms 160.38 μs 6.35 ms +2.9%
PartialSortBenchmark.PartialSort_Select(ItemCount: 100000) 1.18 ms 20.13 μs 1.19 ms -1.6%
PartialSortBenchmark.Array_Select(ItemCount: 1000000) 75.80 ms 85.62 μs 75.76 ms +0.0%
PartialSortBenchmark.PartialSort_Select(ItemCount: 1000000) 8.93 ms 5.02 μs 9.65 ms -7.5%
PartialSortBenchmark.Array_SortPrefix(ItemCount: 100) 476.5 ns 3.1 ns 474.7 ns +0.4%
PartialSortBenchmark.PartialSort_SortPrefix(ItemCount: 100) 330.0 ns 1.5 ns 332.7 ns -0.8%
PartialSortBenchmark.Array_SortPrefix(ItemCount: 1000) 10.34 μs 146.6 ns 10.26 μs +0.8%
PartialSortBenchmark.PartialSort_SortPrefix(ItemCount: 1000) 4.88 μs 8.2 ns 5.48 μs -11.0%
PartialSortBenchmark.Array_SortPrefix(ItemCount: 100000) 6.61 ms 32.40 μs 6.37 ms +3.8%
PartialSortBenchmark.PartialSort_SortPrefix(ItemCount: 100000) 1.21 ms 2.00 μs 1.27 ms -4.7%
PartialSortBenchmark.Array_SortPrefix(ItemCount: 1000000) 75.76 ms 111.12 μs 75.76 ms -0.0%
PartialSortBenchmark.PartialSort_SortPrefix(ItemCount: 1000000) 10.26 ms 426.77 μs 9.91 ms +3.6%
PartialSortBenchmark.Array_TopK(ItemCount: 100) 432.0 ns 0.7 ns 432.6 ns -0.2%
PartialSortBenchmark.PartialSort_TopK(ItemCount: 100) 82.2 ns 0.1 ns 82.1 ns +0.2%
PartialSortBenchmark.Array_TopK(ItemCount: 1000) 8.03 μs 218.7 ns 7.99 μs +0.4%
PartialSortBenchmark.PartialSort_TopK(ItemCount: 1000) 1.54 μs 5.6 ns 1.55 μs -0.4%
PartialSortBenchmark.Array_TopK(ItemCount: 100000) 2.02 ms 26.64 μs 1.95 ms +3.5%
PartialSortBenchmark.PartialSort_TopK(ItemCount: 100000) 380.83 μs 4.82 μs 374.85 μs +1.6%
PartialSortBenchmark.Array_TopK(ItemCount: 1000000) 22.47 ms 160.98 μs 22.55 ms -0.4%
PartialSortBenchmark.PartialSort_TopK(ItemCount: 1000000) 6.36 ms 37.42 μs 6.35 ms +0.1%
PartialSortBenchmark.Array_TopKHeap(ItemCount: 100) 173.6 ns 0.8 ns 174.5 ns -0.5%
PartialSortBenchmark.PartialSort_TopKHeap(ItemCount: 100) 82.3 ns 0.2 ns 82.4 ns -0.1%
PartialSortBenchmark.Array_TopKHeap(ItemCount: 1000) 2.23 μs 6.1 ns 2.24 μs -0.3%
PartialSortBenchmark.PartialSort_TopKHeap(ItemCount: 1000) 1.54 μs 3.5 ns 1.55 μs -0.2%
PartialSortBenchmark.Array_TopKHeap(ItemCount: 100000) 582.83 μs 5.97 μs 559.72 μs +4.1%
PartialSortBenchmark.PartialSort_TopKHeap(ItemCount: 100000) 424.69 μs 2.95 μs 399.91 μs +6.2%
PartialSortBenchmark.Array_TopKHeap(ItemCount: 1000000) 7.57 ms 99.11 μs 7.52 ms +0.7%
PartialSortBenchmark.PartialSort_TopKHeap(ItemCount: 1000000) 6.35 ms 36.43 μs 6.35 ms -0.1%
BitSetBenchmark.BitArray_Xor(ItemCount: 1024) 94.8 ns 2.5 ns 93.9 ns +0.9%
BitSetBenchmark.BitSet_Xor(ItemCount: 1024) 1.23 μs 3.4 ns 1.23 μs -0.2%
BitSetBenchmark.BitArray_Xor(ItemCount: 1000000) 45.13 μs 376.8 ns 45.82 μs -1.5%
BitSetBenchmark.BitSet_Xor(ItemCount: 1000000) 5.04 ms 7.95 μs 5.04 ms -0.0%
EnumSetBenchmark.HashSet_Add 582.4 ns 2.8 ns 581.0 ns +0.3%
EnumSetBenchmark.EnumSet_Add 84.5 ns 1.4 ns 86.3 ns -2.1%
BloomFilterBenchmark.HashSet_Add(ItemCount: 1000) 12.42 μs 89.0 ns 12.43 μs -0.1%
SparseSetBenchmark.HashSet_Add(ItemCount: 1000) 6.84 μs 40.2 ns 6.63 μs +3.1%
BloomFilterBenchmark.BloomFilter_Add(ItemCount: 1000) 16.37 μs 12.0 ns 16.38 μs -0.0%
SparseSetBenchmark.SparseSet_Add(ItemCount: 1000) 6.59 μs 84.5 ns 6.35 μs +3.8%
BloomFilterBenchmark.HashSet_Add(ItemCount: 100000) 4.74 ms 123.62 μs 4.75 ms -0.2%
SparseSetBenchmark.HashSet_Add(ItemCount: 100000) 1.69 ms 23.54 μs 1.69 ms +0.0%
BloomFilterBenchmark.BloomFilter_Add(ItemCount: 100000) 1.26 ms 994.6 ns 1.24 ms +1.7%
SparseSetBenchmark.SparseSet_Add(ItemCount: 100000) 1.51 ms 51.49 μs 1.45 ms +3.8%
SparseSetBenchmark.HashSet_ClearRefill(ItemCount: 1000) 6.10 μs 15.7 ns 6.10 μs +0.1%
SparseSetBenchmark.SparseSet_ClearRefill(ItemCount: 1000) 5.26 μs 290.5 ns 5.58 μs -5.7%
SparseSetBenchmark.HashSet_ClearRefill(ItemCount: 100000) 1.32 ms 42.81 μs 1.29 ms +2.6%
SparseSetBenchmark.SparseSet_ClearRefill(ItemCount: 100000) 685.96 μs 4.21 μs 705.40 μs -2.8%
EnumSetBenchmark.HashSet_Contains 170.7 ns 0.1 ns 171.1 ns -0.2%
EnumSetBenchmark.EnumSet_Contains 51.5 ns 0.0 ns 51.6 ns -0.2%
BloomFilterBenchmark.HashSet_Contains(ItemCount: 1000) 4.74 μs 2.6 ns 4.73 μs +0.1%
SparseSetBenchmark.HashSet_Contains(ItemCount: 1000) 4.61 μs 5.4 ns 4.63 μs -0.4%
BloomFilterBenchmark.BloomFilter_Contains(ItemCount: 1000) 14.19 μs 22.6 ns 14.18 μs +0.0%
SparseSetBenchmark.SparseSet_Contains(ItemCount: 1000) 1.43 μs 2.2 ns 1.43 μs +0.0%
BloomFilterBenchmark.HashSet_Contains(ItemCount: 100000) 1.52 ms 3.86 μs 1.51 ms +0.6%
SparseSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.28 ms 6.78 μs 1.28 ms +0.6%
BloomFilterBenchmark.BloomFilter_Contains(ItemCount: 100000) 982.57 μs 1.32 μs 982.37 μs +0.0%
SparseSetBenchmark.SparseSet_Contains(ItemCount: 100000) 266.36 μs 883.1 ns 264.92 μs +0.5%
BloomFilterBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.57 μs 4.9 ns 4.57 μs -0.1%
BloomFilterBenchmark.BloomFilter_ContainsMissing(ItemCount: 1000) 3.98 μs 5.9 ns 3.98 μs +0.0%
BloomFilterBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 2.00 ms 6.56 μs 2.01 ms -0.3%
BloomFilterBenchmark.BloomFilter_ContainsMissing(ItemCount: 100000) 1.67 ms 2.06 μs 1.67 ms -0.1%
CelerityMultiSetBenchmark.Dictionary_Count(ItemCount: 1000) 9.82 μs 36.5 ns 9.77 μs +0.5%
CelerityMultiSetBenchmark.CelerityMultiSet_Count(ItemCount: 1000) 5.33 μs 18.8 ns 5.32 μs +0.3%
CelerityMultiSetBenchmark.Dictionary_Count(ItemCount: 100000) 1.34 ms 11.79 μs 1.34 ms +0.1%
CelerityMultiSetBenchmark.CelerityMultiSet_Count(ItemCount: 100000) 688.42 μs 28.32 μs 679.31 μs +1.3%
SortedSpanBenchmark.HashSet_Except(ItemCount: 1000) 12.60 μs 104.6 ns 12.55 μs +0.4%
SortedSpanBenchmark.Linq_ExceptLinq(ItemCount: 1000) 20.68 μs 43.4 ns 21.02 μs -1.6%
SortedSpanBenchmark.SortedSpan_Except(ItemCount: 1000) 2.36 μs 71.2 ns 2.45 μs -3.8%
SortedSpanBenchmark.HashSet_Except(ItemCount: 100000) 2.62 ms 15.77 μs 2.66 ms -1.5%
SortedSpanBenchmark.Linq_ExceptLinq(ItemCount: 100000) 3.83 ms 50.49 μs 3.85 ms -0.5%
SortedSpanBenchmark.SortedSpan_Except(ItemCount: 100000) 998.69 μs 5.60 μs 992.60 μs +0.6%
SwissDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.08 μs 75.5 ns 13.00 μs +0.6%
SwissDictionaryBenchmark.SwissDictionary_Insert(ItemCount: 1000) 29.75 μs 270.0 ns 29.33 μs +1.4%
SwissDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 4.83 ms 206.95 μs 4.91 ms -1.5%
SwissDictionaryBenchmark.SwissDictionary_Insert(ItemCount: 100000) 3.86 ms 38.94 μs 3.88 ms -0.7%
SortedSpanBenchmark.HashSet_Intersect(ItemCount: 1000) 20.74 μs 225.9 ns 21.29 μs -2.6%
SortedSpanBenchmark.Linq_IntersectLinq(ItemCount: 1000) 15.28 μs 77.0 ns 15.00 μs +1.9%
SortedSpanBenchmark.SortedSpan_Intersect(ItemCount: 1000) 2.58 μs 54.4 ns 2.75 μs -6.1%
SortedSpanBenchmark.HashSet_Intersect(ItemCount: 100000) 4.22 ms 46.73 μs 4.20 ms +0.3%
SortedSpanBenchmark.Linq_IntersectLinq(ItemCount: 100000) 3.03 ms 20.97 μs 2.96 ms +2.3%
SortedSpanBenchmark.SortedSpan_Intersect(ItemCount: 100000) 970.56 μs 3.73 μs 969.06 μs +0.2%
SortedSpanBenchmark.HashSet_IntersectAsymmetric(ItemCount: 1000) 8.61 μs 158.7 ns 8.52 μs +1.1%
SortedSpanBenchmark.SortedSpan_IntersectAsymmetric(ItemCount: 1000) 108.4 ns 0.8 ns 108.6 ns -0.2%
SortedSpanBenchmark.HashSet_IntersectAsymmetric(ItemCount: 100000) 1.75 ms 13.03 μs 1.75 ms +0.2%
SortedSpanBenchmark.SortedSpan_IntersectAsymmetric(ItemCount: 100000) 14.06 μs 318.7 ns 12.92 μs +8.8%
SortedSpanBenchmark.HashSet_IntersectCount(ItemCount: 1000) 12.65 μs 129.1 ns 12.41 μs +1.9%
SortedSpanBenchmark.SortedSpan_IntersectCount(ItemCount: 1000) 2.59 μs 54.5 ns 2.63 μs -1.7%
SortedSpanBenchmark.HashSet_IntersectCount(ItemCount: 100000) 2.66 ms 22.41 μs 2.61 ms +1.9%
SortedSpanBenchmark.SortedSpan_IntersectCount(ItemCount: 100000) 948.03 μs 478.0 ns 961.06 μs -1.4%
CelerityMultiSetBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.64 μs 19.7 ns 4.62 μs +0.3%
SwissDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.73 μs 118.0 ns 6.18 μs -23.5% ✅
CelerityMultiSetBenchmark.CelerityMultiSet_Lookup(ItemCount: 1000) 1.95 μs 2.7 ns 1.95 μs +0.2%
SwissDictionaryBenchmark.SwissDictionary_Lookup(ItemCount: 1000) 3.24 μs 252.6 ns 2.88 μs +12.5% ⚠️
CelerityMultiSetBenchmark.Dictionary_Lookup(ItemCount: 100000) 558.78 μs 978.8 ns 584.03 μs -4.3%
SwissDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.61 ms 8.71 μs 1.60 ms +0.8%
CelerityMultiSetBenchmark.CelerityMultiSet_Lookup(ItemCount: 100000) 214.85 μs 223.2 ns 214.56 μs +0.1%
SwissDictionaryBenchmark.SwissDictionary_Lookup(ItemCount: 100000) 672.89 μs 11.64 μs 667.85 μs +0.8%
SegmentTreeBenchmark.Array_Mixed(ItemCount: 1000) 158.67 μs 569.4 ns 159.18 μs -0.3%
SegmentTreeBenchmark.SegmentTree_Mixed(ItemCount: 1000) 38.45 μs 261.1 ns 38.97 μs -1.3%
SegmentTreeBenchmark.Array_Mixed(ItemCount: 100000) 23.53 ms 42.78 μs 23.55 ms -0.1%
SegmentTreeBenchmark.SegmentTree_Mixed(ItemCount: 100000) 1.33 ms 14.91 μs 1.31 ms +1.1%
SortedSpanBenchmark.HashSet_Overlaps(ItemCount: 1000) 8.27 μs 86.4 ns 8.12 μs +1.9%
SortedSpanBenchmark.SortedSpan_Overlaps(ItemCount: 1000) 8.3 ns 0.2 ns 8.5 ns -2.1%
SortedSpanBenchmark.HashSet_Overlaps(ItemCount: 100000) 1.31 ms 32.63 μs 1.29 ms +1.7%
SortedSpanBenchmark.SortedSpan_Overlaps(ItemCount: 100000) 4.2 ns 0.0 ns 4.2 ns -0.0%
SegmentTreeBenchmark.Array_RangeMin(ItemCount: 1000) 207.44 μs 591.6 ns 207.40 μs +0.0%
SegmentTreeBenchmark.SegmentTree_RangeMin(ItemCount: 1000) 21.38 μs 53.6 ns 21.36 μs +0.1%
SegmentTreeBenchmark.Array_RangeMin(ItemCount: 100000) 40.15 ms 5.80 ms 40.61 ms -1.1%
SegmentTreeBenchmark.SegmentTree_RangeMin(ItemCount: 100000) 75.61 μs 1.28 μs 74.42 μs +1.6%
EnumSetBenchmark.HashSet_Remove 2.65 μs 400.3 ns 2.19 μs +21.1%
EnumSetBenchmark.EnumSet_Remove 967.7 ns 132.8 ns 1.07 μs -9.9%
CelerityMultiSetBenchmark.Dictionary_Remove(ItemCount: 1000) 47.73 μs 3.93 μs 49.84 μs -4.2%
SwissDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 78.63 μs 6.98 μs 76.20 μs +3.2%
CelerityMultiSetBenchmark.CelerityMultiSet_Remove(ItemCount: 1000) 83.81 μs 7.31 μs 85.05 μs -1.5%
SwissDictionaryBenchmark.SwissDictionary_Remove(ItemCount: 1000) 72.90 μs 4.56 μs 73.00 μs -0.1%
SparseSetBenchmark.HashSet_Remove(ItemCount: 1000) 25.91 μs 2.75 μs 26.17 μs -1.0%
SparseSetBenchmark.SparseSet_Remove(ItemCount: 1000) 23.48 μs 2.54 μs 21.06 μs +11.5%
CelerityMultiSetBenchmark.Dictionary_Remove(ItemCount: 100000) 568.72 μs 11.35 μs 577.28 μs -1.5%
SwissDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.02 ms 29.67 μs 1.99 ms +1.6%
CelerityMultiSetBenchmark.CelerityMultiSet_Remove(ItemCount: 100000) 1.47 ms 66.48 μs 1.41 ms +4.7%
SwissDictionaryBenchmark.SwissDictionary_Remove(ItemCount: 100000) 1.30 ms 29.82 μs 1.28 ms +1.1%
SparseSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.49 ms 22.74 μs 1.47 ms +0.8%
SparseSetBenchmark.SparseSet_Remove(ItemCount: 100000) 656.42 μs 12.24 μs 646.47 μs +1.5%
EnumSetBenchmark.HashSet_Union 411.9 ns 5.4 ns 401.3 ns +2.7%
EnumSetBenchmark.EnumSet_Union 22.8 ns 0.4 ns 22.7 ns +0.5%
SortedSpanBenchmark.HashSet_Union(ItemCount: 1000) 18.67 μs 81.3 ns 18.57 μs +0.5%
SortedSpanBenchmark.Linq_UnionLinq(ItemCount: 1000) 20.22 μs 98.2 ns 20.06 μs +0.8%
SortedSpanBenchmark.SortedSpan_Union(ItemCount: 1000) 2.89 μs 6.8 ns 2.90 μs -0.1%
SortedSpanBenchmark.HashSet_Union(ItemCount: 100000) 3.61 ms 51.06 μs 3.58 ms +0.6%
SortedSpanBenchmark.Linq_UnionLinq(ItemCount: 100000) 5.24 ms 292.13 μs 6.18 ms -15.2% ✅
SortedSpanBenchmark.SortedSpan_Union(ItemCount: 100000) 1.01 ms 7.34 μs 1.02 ms -0.1%
CuckooFilterBenchmark.HashSet_Add(ItemCount: 1000) 12.32 μs 132.3 ns 13.24 μs -6.9%
HyperLogLogBenchmark.HashSet_Add(ItemCount: 1000) 11.98 μs 142.4 ns 12.04 μs -0.5%
CuckooFilterBenchmark.CuckooFilter_Add(ItemCount: 1000) 7.13 μs 66.3 ns 7.24 μs -1.4%
HyperLogLogBenchmark.HyperLogLog_Add(ItemCount: 1000) 26.87 μs 47.7 ns 27.13 μs -0.9%
CuckooFilterBenchmark.HashSet_Add(ItemCount: 100000) 4.71 ms 94.76 μs 4.80 ms -1.8%
HyperLogLogBenchmark.HashSet_Add(ItemCount: 100000) 4.83 ms 65.07 μs 4.84 ms -0.3%
CuckooFilterBenchmark.CuckooFilter_Add(ItemCount: 100000) 2.08 ms 7.60 μs 2.07 ms +0.5%
HyperLogLogBenchmark.HyperLogLog_Add(ItemCount: 100000) 575.44 μs 1.12 μs 575.45 μs -0.0%
XorFilterBenchmark.HashSet_Build(ItemCount: 1000) 8.16 μs 246.0 ns 7.99 μs +2.1%
XorFilterBenchmark.XorFilter_Build(ItemCount: 1000) 39.10 μs 1.21 μs 38.55 μs +1.4%
XorFilterBenchmark.HashSet_Build(ItemCount: 100000) 2.08 ms 29.77 μs 2.09 ms -0.5%
XorFilterBenchmark.XorFilter_Build(ItemCount: 100000) 12.39 ms 298.02 μs 12.34 ms +0.4%
CuckooFilterBenchmark.HashSet_Contains(ItemCount: 1000) 4.72 μs 4.1 ns 4.72 μs +0.1%
XorFilterBenchmark.HashSet_Contains(ItemCount: 1000) 4.75 μs 35.1 ns 4.73 μs +0.4%
CuckooFilterBenchmark.CuckooFilter_Contains(ItemCount: 1000) 4.92 μs 5.5 ns 4.92 μs +0.1%
XorFilterBenchmark.XorFilter_Contains(ItemCount: 1000) 6.77 μs 4.1 ns 6.77 μs -0.0%
CuckooFilterBenchmark.HashSet_Contains(ItemCount: 100000) 1.59 ms 13.13 μs 1.60 ms -0.7%
XorFilterBenchmark.HashSet_Contains(ItemCount: 100000) 1.60 ms 3.30 μs 1.55 ms +3.5%
CuckooFilterBenchmark.CuckooFilter_Contains(ItemCount: 100000) 1.75 ms 1.75 μs 1.74 ms +0.7%
XorFilterBenchmark.XorFilter_Contains(ItemCount: 100000) 703.51 μs 259.4 ns 703.64 μs -0.0%
CuckooFilterBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.54 μs 6.6 ns 4.55 μs -0.2%
XorFilterBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.54 μs 5.7 ns 4.54 μs +0.0%
CuckooFilterBenchmark.CuckooFilter_ContainsMissing(ItemCount: 1000) 8.43 μs 7.7 ns 8.43 μs -0.0%
XorFilterBenchmark.XorFilter_ContainsMissing(ItemCount: 1000) 6.77 μs 2.1 ns 6.77 μs -0.0%
CuckooFilterBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 1.93 ms 5.11 μs 1.92 ms +0.6%
XorFilterBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 1.92 ms 23.71 μs 1.94 ms -1.0%
CuckooFilterBenchmark.CuckooFilter_ContainsMissing(ItemCount: 100000) 883.67 μs 11.17 μs 888.84 μs -0.6%
XorFilterBenchmark.XorFilter_ContainsMissing(ItemCount: 100000) 705.39 μs 408.5 ns 705.79 μs -0.1%
HyperLogLogBenchmark.HashSet_Estimate(ItemCount: 1000) 0.0 ns 0.0 ns 0.0 ns +96.7%
HyperLogLogBenchmark.HyperLogLog_Estimate(ItemCount: 1000) 23.44 μs 13.0 ns 23.45 μs -0.1%
HyperLogLogBenchmark.HashSet_Estimate(ItemCount: 100000) 0.0 ns 0.0 ns 0.0 ns +59.9%
HyperLogLogBenchmark.HyperLogLog_Estimate(ItemCount: 100000) 22.98 μs 4.7 ns 22.97 μs +0.0%
SmallDictionaryBenchmark.Dictionary_Insert(ItemCount: 8) 165.6 ns 6.1 ns 168.6 ns -1.8%
SmallDictionaryBenchmark.SmallDictionary_Insert(ItemCount: 8) 88.4 ns 4.1 ns 85.9 ns +2.9%
SmallDictionaryBenchmark.Dictionary_Insert(ItemCount: 64) 758.6 ns 2.7 ns 778.6 ns -2.6%
SmallDictionaryBenchmark.SmallDictionary_Insert(ItemCount: 64) 1.08 μs 14.4 ns 1.09 μs -0.7%
HashCachingDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.29 μs 207.8 ns 14.07 μs -5.5%
HashCachingDictionaryBenchmark.HashCachingDictionary_Insert(ItemCount: 1000) 10.86 μs 624.5 ns 11.59 μs -6.3%
HashCachingDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 4.75 ms 104.66 μs 4.73 ms +0.5%
HashCachingDictionaryBenchmark.HashCachingDictionary_Insert(ItemCount: 100000) 6.57 ms 364.92 μs 6.75 ms -2.6%
SmallDictionaryBenchmark.Dictionary_Lookup(ItemCount: 8) 36.9 ns 0.2 ns 36.8 ns +0.2%
SmallDictionaryBenchmark.SmallDictionary_Lookup(ItemCount: 8) 29.5 ns 3.8 ns 29.3 ns +0.7%
SmallDictionaryBenchmark.Dictionary_Lookup(ItemCount: 64) 296.3 ns 0.4 ns 296.5 ns -0.1%
SmallDictionaryBenchmark.SmallDictionary_Lookup(ItemCount: 64) 1.10 μs 9.4 ns 1.11 μs -0.8%
HashCachingDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.73 μs 15.5 ns 4.76 μs -0.6%
HashCachingDictionaryBenchmark.HashCachingDictionary_Lookup(ItemCount: 1000) 2.64 μs 8.3 ns 2.66 μs -0.9%
HashCachingDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.56 ms 49.25 μs 1.61 ms -3.0%
HashCachingDictionaryBenchmark.HashCachingDictionary_Lookup(ItemCount: 100000) 849.54 μs 25.75 μs 820.26 μs +3.6%
SmallDictionaryBenchmark.Dictionary_Remove(ItemCount: 8) 1.45 μs 260.2 ns 1.24 μs +16.9%
SmallDictionaryBenchmark.SmallDictionary_Remove(ItemCount: 8) 1.11 μs 112.8 ns 1.52 μs -26.7% ✅
SmallDictionaryBenchmark.Dictionary_Remove(ItemCount: 64) 6.47 μs 219.1 ns 4.86 μs +33.1% ⚠️
SmallDictionaryBenchmark.SmallDictionary_Remove(ItemCount: 64) 24.75 μs 4.52 μs 21.79 μs +13.6%
HashCachingDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 81.46 μs 7.84 μs 82.84 μs -1.7%
HashCachingDictionaryBenchmark.HashCachingDictionary_Remove(ItemCount: 1000) 126.21 μs 11.55 μs 126.44 μs -0.2%
CuckooFilterBenchmark.HashSet_Remove(ItemCount: 1000) 13.01 μs 212.9 ns 13.46 μs -3.4%
CuckooFilterBenchmark.CuckooFilter_Remove(ItemCount: 1000) 12.94 μs 69.9 ns 13.18 μs -1.9%
HashCachingDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.07 ms 14.62 μs 2.05 ms +0.8%
HashCachingDictionaryBenchmark.HashCachingDictionary_Remove(ItemCount: 100000) 1.82 ms 81.80 μs 1.89 ms -3.8%
CuckooFilterBenchmark.HashSet_Remove(ItemCount: 100000) 3.80 ms 23.35 μs 3.88 ms -2.2%
CuckooFilterBenchmark.CuckooFilter_Remove(ItemCount: 100000) 3.98 ms 11.16 μs 3.98 ms +0.1%
CompressedIntSetBenchmark.HashSet_Add(ItemCount: 1000) 12.16 μs 201.5 ns 11.98 μs +1.5%
HashCachingSetBenchmark.HashSet_Add(ItemCount: 1000) 12.30 μs 89.8 ns 12.05 μs +2.1%
LongSetBenchmark.HashSet_Add(ItemCount: 1000) 12.70 μs 82.3 ns 13.10 μs -3.1%
CompressedIntSetBenchmark.CompressedIntSet_Add(ItemCount: 1000) 33.79 μs 952.4 ns 34.04 μs -0.8%
HashCachingSetBenchmark.HashCachingSet_Add(ItemCount: 1000) 10.85 μs 51.9 ns 11.00 μs -1.4%
LongSetBenchmark.LongSet_Add(ItemCount: 1000) 9.06 μs 28.8 ns 9.18 μs -1.3%
CompressedIntSetBenchmark.HashSet_Add(ItemCount: 100000) 3.50 ms 50.97 μs 3.48 ms +0.7%
HashCachingSetBenchmark.HashSet_Add(ItemCount: 100000) 4.36 ms 523.65 μs 4.45 ms -2.0%
LongSetBenchmark.HashSet_Add(ItemCount: 100000) 4.38 ms 110.35 μs 4.58 ms -4.3%
CompressedIntSetBenchmark.CompressedIntSet_Add(ItemCount: 100000) 10.72 ms 34.06 μs 10.65 ms +0.6%
HashCachingSetBenchmark.HashCachingSet_Add(ItemCount: 100000) 5.32 ms 59.38 μs 5.10 ms +4.4%
LongSetBenchmark.LongSet_Add(ItemCount: 100000) 6.05 ms 41.42 μs 6.07 ms -0.3%
FrozenCelerityDictionaryBenchmark.FrozenDictionary_Build(ItemCount: 1000) 159.01 μs 865.5 ns 161.76 μs -1.7%
FrozenCelerityDictionaryBenchmark.FrozenCelerityDictionary_Build(ItemCount: 1000) 3.67 ms 128.65 μs 3.51 ms +4.6%
FrozenCelerityDictionaryBenchmark.FrozenDictionary_Build(ItemCount: 100000) 28.40 ms 263.91 μs 28.65 ms -0.9%
FrozenCelerityDictionaryBenchmark.FrozenCelerityDictionary_Build(ItemCount: 100000) 1.52 s 34.27 ms 1.51 s +0.3%
CompressedIntSetBenchmark.HashSet_Contains(ItemCount: 1000) 4.70 μs 7.1 ns 4.70 μs +0.0%
HashCachingSetBenchmark.HashSet_Contains(ItemCount: 1000) 4.73 μs 6.6 ns 4.74 μs -0.3%
LongSetBenchmark.HashSet_Contains(ItemCount: 1000) 4.80 μs 52.3 ns 5.04 μs -4.8%
CompressedIntSetBenchmark.CompressedIntSet_Contains(ItemCount: 1000) 13.48 μs 11.2 ns 13.48 μs -0.0%
HashCachingSetBenchmark.HashCachingSet_Contains(ItemCount: 1000) 2.53 μs 3.4 ns 2.53 μs -0.2%
LongSetBenchmark.LongSet_Contains(ItemCount: 1000) 2.00 μs 7.1 ns 2.01 μs -0.1%
StringKeyProbeBenchmark.HashSet_Contains(ItemCount: 1000) 18.11 μs 65.3 ns 17.95 μs +0.9%
StringKeyProbeBenchmark.CeleritySet_Contains(ItemCount: 1000) 24.37 μs 196.7 ns 24.41 μs -0.2%
CompressedIntSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.53 ms 45.49 μs 1.60 ms -4.6%
HashCachingSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.56 ms 1.32 μs 1.58 ms -0.9%
LongSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.63 ms 10.14 μs 1.64 ms -0.7%
CompressedIntSetBenchmark.CompressedIntSet_Contains(ItemCount: 100000) 8.34 ms 11.26 μs 8.30 ms +0.5%
HashCachingSetBenchmark.HashCachingSet_Contains(ItemCount: 100000) 728.55 μs 3.94 μs 726.70 μs +0.3%
LongSetBenchmark.LongSet_Contains(ItemCount: 100000) 639.46 μs 3.80 μs 640.60 μs -0.2%
StringKeyProbeBenchmark.HashSet_Contains(ItemCount: 100000) 3.40 ms 32.78 μs 3.42 ms -0.5%
StringKeyProbeBenchmark.CeleritySet_Contains(ItemCount: 100000) 4.76 ms 32.63 μs 4.68 ms +1.6%
HashCachingSetBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.54 μs 6.8 ns 4.54 μs +0.1%
HashCachingSetBenchmark.HashCachingSet_ContainsMissing(ItemCount: 1000) 2.96 μs 4.1 ns 2.96 μs -0.0%
HashCachingSetBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 1.94 ms 7.43 μs 1.88 ms +3.0%
HashCachingSetBenchmark.HashCachingSet_ContainsMissing(ItemCount: 100000) 1.13 ms 2.17 μs 1.13 ms -0.3%
CompressedIntSetBenchmark.HashSet_Except(ItemCount: 1000) 58.71 μs 7.32 μs 59.52 μs -1.4%
CompressedIntSetBenchmark.CompressedIntSet_Except(ItemCount: 1000) 71.08 μs 9.44 μs 68.14 μs +4.3%
CompressedIntSetBenchmark.HashSet_Except(ItemCount: 100000) 2.52 ms 16.21 μs 2.53 ms -0.6%
CompressedIntSetBenchmark.CompressedIntSet_Except(ItemCount: 100000) 1.10 ms 17.14 μs 1.09 ms +1.2%
RobinHoodDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 12.78 μs 134.9 ns 14.07 μs -9.2% ✅
RobinHoodDictionaryBenchmark.RobinHoodDictionary_Insert(ItemCount: 1000) 17.65 μs 58.7 ns 17.59 μs +0.3%
RobinHoodDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 4.69 ms 90.10 μs 4.73 ms -0.8%
RobinHoodDictionaryBenchmark.RobinHoodDictionary_Insert(ItemCount: 100000) 8.15 ms 484.82 μs 7.97 ms +2.2%
CompressedIntSetBenchmark.HashSet_IntersectClustered(ItemCount: 1000) 36.15 μs 4.76 μs 41.24 μs -12.3%
CompressedIntSetBenchmark.CompressedIntSet_IntersectClustered(ItemCount: 1000) 1.63 μs 325.3 ns 1.66 μs -1.4%
CompressedIntSetBenchmark.HashSet_IntersectClustered(ItemCount: 100000) 968.43 μs 10.81 μs 960.37 μs +0.8%
CompressedIntSetBenchmark.CompressedIntSet_IntersectClustered(ItemCount: 100000) 1.61 μs 366.3 ns 1.57 μs +2.3%
CompressedIntSetBenchmark.HashSet_IntersectDense(ItemCount: 1000) 46.38 μs 5.80 μs 50.72 μs -8.5%
CompressedIntSetBenchmark.CompressedIntSet_IntersectDense(ItemCount: 1000) 53.47 μs 5.15 μs 55.44 μs -3.6%
CompressedIntSetBenchmark.HashSet_IntersectDense(ItemCount: 100000) 3.08 ms 18.42 μs 3.13 ms -1.5%
CompressedIntSetBenchmark.CompressedIntSet_IntersectDense(ItemCount: 100000) 85.45 μs 26.91 μs 93.67 μs -8.8%
CompressedIntSetBenchmark.HashSet_IntersectSparse(ItemCount: 1000) 56.75 μs 4.17 μs 55.82 μs +1.7%
CompressedIntSetBenchmark.CompressedIntSet_IntersectSparse(ItemCount: 1000) 55.79 μs 7.11 μs 51.58 μs +8.1%
CompressedIntSetBenchmark.HashSet_IntersectSparse(ItemCount: 100000) 3.96 ms 131.68 μs 3.93 ms +0.6%
CompressedIntSetBenchmark.CompressedIntSet_IntersectSparse(ItemCount: 100000) 953.17 μs 10.42 μs 1.01 ms -5.7%
StringKeyProbeBenchmark.Dictionary_Lookup(ItemCount: 1000) 18.71 μs 239.7 ns 18.75 μs -0.2%
StringKeyProbeBenchmark.CelerityDictionary_Lookup(ItemCount: 1000) 26.70 μs 67.4 ns 26.52 μs +0.7%
FrozenCelerityDictionaryBenchmark.FrozenDictionary_Lookup(ItemCount: 1000) 7.33 μs 9.7 ns 7.33 μs +0.0%
RobinHoodDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.74 μs 9.7 ns 5.94 μs -20.2%
FrozenCelerityDictionaryBenchmark.FrozenCelerityDictionary_Lookup(ItemCount: 1000) 88.05 μs 2.63 μs 88.09 μs -0.0%
RobinHoodDictionaryBenchmark.RobinHoodDictionary_Lookup(ItemCount: 1000) 2.82 μs 6.4 ns 2.82 μs +0.2%
StringKeyProbeBenchmark.Dictionary_Lookup(ItemCount: 100000) 3.50 ms 55.45 μs 3.55 ms -1.5%
StringKeyProbeBenchmark.CelerityDictionary_Lookup(ItemCount: 100000) 5.08 ms 56.10 μs 5.13 ms -0.9%
FrozenCelerityDictionaryBenchmark.FrozenDictionary_Lookup(ItemCount: 100000) 2.02 ms 29.00 μs 1.99 ms +1.5%
RobinHoodDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.62 ms 7.36 μs 1.61 ms +0.8%
FrozenCelerityDictionaryBenchmark.FrozenCelerityDictionary_Lookup(ItemCount: 100000) 7.62 ms 53.74 μs 7.64 ms -0.4%
RobinHoodDictionaryBenchmark.RobinHoodDictionary_Lookup(ItemCount: 100000) 835.66 μs 16.02 μs 854.50 μs -2.2%
StringKeyProbeBenchmark.Dictionary_LookupMissing(ItemCount: 1000) 14.93 μs 61.0 ns 14.91 μs +0.2%
StringKeyProbeBenchmark.CelerityDictionary_LookupMissing(ItemCount: 1000) 28.68 μs 522.6 ns 28.58 μs +0.4%
StringKeyProbeBenchmark.Dictionary_LookupMissing(ItemCount: 100000) 3.86 ms 24.93 μs 3.87 ms -0.2%
StringKeyProbeBenchmark.CelerityDictionary_LookupMissing(ItemCount: 100000) 5.77 ms 50.06 μs 5.67 ms +1.6%
LongSetBenchmark.HashSet_Remove(ItemCount: 1000) 75.98 μs 6.31 μs 75.92 μs +0.1%
RobinHoodDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 84.76 μs 7.87 μs 84.26 μs +0.6%
LongSetBenchmark.LongSet_Remove(ItemCount: 1000) 83.59 μs 8.65 μs 87.73 μs -4.7%
RobinHoodDictionaryBenchmark.RobinHoodDictionary_Remove(ItemCount: 1000) 122.35 μs 5.42 μs 110.87 μs +10.4%
HashCachingSetBenchmark.HashSet_Remove(ItemCount: 1000) 28.59 μs 4.84 μs 26.33 μs +8.6%
HashCachingSetBenchmark.HashCachingSet_Remove(ItemCount: 1000) 117.13 μs 12.97 μs 116.33 μs +0.7%
LongSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.97 ms 11.44 μs 1.99 ms -1.0%
RobinHoodDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.05 ms 14.67 μs 2.03 ms +0.8%
LongSetBenchmark.LongSet_Remove(ItemCount: 100000) 1.43 ms 18.05 μs 1.43 ms -0.2%
RobinHoodDictionaryBenchmark.RobinHoodDictionary_Remove(ItemCount: 100000) 1.82 ms 79.64 μs 1.76 ms +3.4%
HashCachingSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.72 ms 18.58 μs 1.72 ms +0.1%
HashCachingSetBenchmark.HashCachingSet_Remove(ItemCount: 100000) 1.56 ms 13.68 μs 1.55 ms +0.4%
FrozenCelerityDictionaryBenchmark.FrozenDictionary_SpanLookup(ItemCount: 1000) 30.15 μs 127.4 ns 30.27 μs -0.4%
FrozenCelerityDictionaryBenchmark.FrozenCelerityDictionary_SpanLookup(ItemCount: 1000) 91.24 μs 157.4 ns 91.40 μs -0.2%
FrozenCelerityDictionaryBenchmark.FrozenDictionary_SpanLookup(ItemCount: 100000) 5.52 ms 246.65 μs 5.79 ms -4.6%
FrozenCelerityDictionaryBenchmark.FrozenCelerityDictionary_SpanLookup(ItemCount: 100000) 8.20 ms 27.96 μs 8.60 ms -4.6%
CompressedIntSetBenchmark.HashSet_Union(ItemCount: 1000) 34.16 μs 4.39 μs 27.52 μs +24.1% ⚠️
CompressedIntSetBenchmark.CompressedIntSet_Union(ItemCount: 1000) 85.12 μs 6.95 μs 77.19 μs +10.3%
CompressedIntSetBenchmark.HashSet_Union(ItemCount: 100000) 4.80 ms 1.01 ms 4.43 ms +8.2%
CompressedIntSetBenchmark.CompressedIntSet_Union(ItemCount: 100000) 1.18 ms 28.90 μs 1.24 ms -4.8%
EnumMapBenchmark.Dictionary_Add 471.8 ns 7.0 ns 464.5 ns +1.6%
EnumMapBenchmark.EnumMap_Add 127.3 ns 3.9 ns 122.4 ns +4.0%
SmallSetBenchmark.HashSet_Add(ItemCount: 8) 123.1 ns 3.3 ns 123.3 ns -0.1%
SmallSetBenchmark.SmallSet_Add(ItemCount: 8) 44.0 ns 1.8 ns 46.4 ns -5.2%
SmallSetBenchmark.HashSet_Add(ItemCount: 64) 568.2 ns 10.5 ns 558.9 ns +1.7%
SmallSetBenchmark.SmallSet_Add(ItemCount: 64) 1.74 μs 19.1 ns 1.71 μs +1.3%
RobinHoodSetBenchmark.HashSet_Add(ItemCount: 1000) 8.87 μs 79.4 ns 9.14 μs -3.0%
TopKSketchBenchmark.Dictionary_Add(ItemCount: 1000) 9.31 μs 142.8 ns 10.03 μs -7.1%
RobinHoodSetBenchmark.RobinHoodSet_Add(ItemCount: 1000) 11.12 μs 474.0 ns 11.24 μs -1.1%
TopKSketchBenchmark.TopKSketch_Add(ItemCount: 1000) 69.16 μs 7.19 μs 76.90 μs -10.1%
RobinHoodSetBenchmark.HashSet_Add(ItemCount: 100000) 3.42 ms 171.76 μs 3.34 ms +2.5%
TopKSketchBenchmark.Dictionary_Add(ItemCount: 100000) 2.52 ms 55.53 μs 2.59 ms -2.9%
RobinHoodSetBenchmark.RobinHoodSet_Add(ItemCount: 100000) 5.53 ms 141.93 μs 5.61 ms -1.3%
TopKSketchBenchmark.TopKSketch_Add(ItemCount: 100000) 12.69 ms 190.06 μs 12.68 ms +0.0%
RadixSortBenchmark.Array_ArgSort(ItemCount: 100) 672.2 ns 22.6 ns 640.4 ns +5.0%
RadixSortBenchmark.RadixSort_ArgSort(ItemCount: 100) 1.64 μs 43.1 ns 1.68 μs -2.8%
RadixSortBenchmark.Array_ArgSort(ItemCount: 1000) 9.15 μs 93.3 ns 9.52 μs -3.8%
RadixSortBenchmark.RadixSort_ArgSort(ItemCount: 1000) 8.26 μs 310.2 ns 8.80 μs -6.1%
RadixSortBenchmark.Array_ArgSort(ItemCount: 100000) 6.35 ms 26.24 μs 6.46 ms -1.7%
RadixSortBenchmark.RadixSort_ArgSort(ItemCount: 100000) 950.70 μs 6.28 μs 987.09 μs -3.7%
RadixSortBenchmark.Array_ArgSort(ItemCount: 1000000) 75.19 ms 445.89 μs 75.62 ms -0.6%
RadixSortBenchmark.RadixSort_ArgSort(ItemCount: 1000000) 14.02 ms 211.55 μs 14.14 ms -0.9%
SmallSetBenchmark.HashSet_Contains(ItemCount: 8) 22.8 ns 0.3 ns 22.8 ns +0.1%
SmallSetBenchmark.SmallSet_Contains(ItemCount: 8) 21.4 ns 0.2 ns 21.5 ns -0.3%
SmallSetBenchmark.HashSet_Contains(ItemCount: 64) 189.7 ns 0.8 ns 189.7 ns -0.0%
SmallSetBenchmark.SmallSet_Contains(ItemCount: 64) 833.2 ns 10.3 ns 828.3 ns +0.6%
RobinHoodSetBenchmark.HashSet_Contains(ItemCount: 1000) 2.99 μs 5.7 ns 3.01 μs -0.6%
RobinHoodSetBenchmark.RobinHoodSet_Contains(ItemCount: 1000) 1.94 μs 24.0 ns 1.91 μs +1.5%
RobinHoodSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.21 ms 10.53 μs 1.24 ms -2.0%
RobinHoodSetBenchmark.RobinHoodSet_Contains(ItemCount: 100000) 676.07 μs 3.18 μs 677.48 μs -0.2%
RobinHoodSetBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 3.00 μs 8.3 ns 3.02 μs -0.5%
RobinHoodSetBenchmark.RobinHoodSet_ContainsMissing(ItemCount: 1000) 2.06 μs 6.5 ns 2.09 μs -1.5%
RobinHoodSetBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 1.58 ms 8.45 μs 1.59 ms -0.6%
RobinHoodSetBenchmark.RobinHoodSet_ContainsMissing(ItemCount: 100000) 1.15 ms 14.58 μs 1.16 ms -0.8%
EnumMapBenchmark.Dictionary_Enumerate 32.1 ns 1.1 ns 32.5 ns -1.3%
EnumMapBenchmark.EnumMap_Enumerate 28.0 ns 0.1 ns 28.1 ns -0.3%
CelerityMultiMapBenchmark.Dictionary_Insert(ItemCount: 1000) 23.68 μs 1.55 μs 22.94 μs +3.3%
CelerityMultiMapBenchmark.CelerityMultiMap_Insert(ItemCount: 1000) 31.64 μs 1.09 μs 31.47 μs +0.5%
CelerityMultiMapBenchmark.Dictionary_Insert(ItemCount: 100000) 7.16 ms 154.99 μs 7.08 ms +1.1%
CelerityMultiMapBenchmark.CelerityMultiMap_Insert(ItemCount: 100000) 10.95 ms 253.13 μs 10.28 ms +6.6%
CountingSortBenchmark.Array_Keys(ItemCount: 100) 406.9 ns 5.1 ns 413.5 ns -1.6%
RadixSortBenchmark.Array_Keys(ItemCount: 100) 442.9 ns 4.5 ns 445.3 ns -0.5%
CountingSortBenchmark.CountingSort_Keys(ItemCount: 100) 493.5 ns 6.6 ns 490.9 ns +0.5%
RadixSortBenchmark.RadixSort_Keys(ItemCount: 100) 1.26 μs 6.0 ns 1.32 μs -4.4%
CountingSortBenchmark.Array_Keys(ItemCount: 1000) 5.96 μs 93.1 ns 5.90 μs +1.1%
RadixSortBenchmark.Array_Keys(ItemCount: 1000) 7.80 μs 155.3 ns 7.79 μs +0.2%
CountingSortBenchmark.CountingSort_Keys(ItemCount: 1000) 1.77 μs 39.5 ns 2.31 μs -23.4%
RadixSortBenchmark.RadixSort_Keys(ItemCount: 1000) 6.08 μs 82.6 ns 6.16 μs -1.3%
CountingSortBenchmark.Array_Keys(ItemCount: 100000) 3.68 ms 73.74 μs 3.77 ms -2.4%
RadixSortBenchmark.Array_Keys(ItemCount: 100000) 5.90 ms 97.65 μs 5.91 ms -0.1%
CountingSortBenchmark.CountingSort_Keys(ItemCount: 100000) 49.28 μs 182.7 ns 52.83 μs -6.7%
RadixSortBenchmark.RadixSort_Keys(ItemCount: 100000) 608.35 μs 5.22 μs 606.86 μs +0.2%
CountingSortBenchmark.Array_Keys(ItemCount: 1000000) 36.72 ms 42.12 μs 38.08 ms -3.6%
RadixSortBenchmark.Array_Keys(ItemCount: 1000000) 70.33 ms 1.07 ms 71.41 ms -1.5%
CountingSortBenchmark.CountingSort_Keys(ItemCount: 1000000) 487.09 μs 1.48 μs 518.77 μs -6.1%
RadixSortBenchmark.RadixSort_Keys(ItemCount: 1000000) 9.20 ms 1.09 ms 8.35 ms +10.1%
EnumMapBenchmark.Dictionary_Lookup 78.2 ns 0.5 ns 79.1 ns -1.1%
EnumMapBenchmark.EnumMap_Lookup 45.6 ns 0.6 ns 46.2 ns -1.3%
CelerityMultiMapBenchmark.Dictionary_Lookup(ItemCount: 1000) 3.73 μs 198.9 ns 3.36 μs +11.0% ⚠️
CelerityMultiMapBenchmark.CelerityMultiMap_Lookup(ItemCount: 1000) 2.01 μs 24.7 ns 2.05 μs -2.2%
CelerityMultiMapBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.60 ms 7.51 μs 1.61 ms -0.3%
CelerityMultiMapBenchmark.CelerityMultiMap_Lookup(ItemCount: 100000) 820.08 μs 3.35 μs 837.70 μs -2.1%
CountingSortBenchmark.Array_Pairs(ItemCount: 100) 602.6 ns 9.9 ns 612.2 ns -1.6%
RadixSortBenchmark.Array_Pairs(ItemCount: 100) 621.8 ns 7.8 ns 612.1 ns +1.6%
CountingSortBenchmark.CountingSort_Pairs(ItemCount: 100) 743.4 ns 29.8 ns 788.1 ns -5.7%
RadixSortBenchmark.RadixSort_Pairs(ItemCount: 100) 1.50 μs 12.9 ns 1.55 μs -3.1%
CountingSortBenchmark.Array_Pairs(ItemCount: 1000) 11.04 μs 382.6 ns 11.25 μs -1.9%
RadixSortBenchmark.Array_Pairs(ItemCount: 1000) 9.02 μs 87.9 ns 9.03 μs -0.1%
CountingSortBenchmark.CountingSort_Pairs(ItemCount: 1000) 2.88 μs 73.2 ns 2.94 μs -2.1%
RadixSortBenchmark.RadixSort_Pairs(ItemCount: 1000) 8.16 μs 556.7 ns 8.26 μs -1.3%
CountingSortBenchmark.Array_Pairs(ItemCount: 100000) 4.68 ms 11.63 μs 4.91 ms -4.7%
RadixSortBenchmark.Array_Pairs(ItemCount: 100000) 6.24 ms 32.38 μs 6.23 ms +0.2%
CountingSortBenchmark.CountingSort_Pairs(ItemCount: 100000) 184.21 μs 5.38 μs 190.02 μs -3.1%
RadixSortBenchmark.RadixSort_Pairs(ItemCount: 100000) 967.48 μs 10.02 μs 967.62 μs -0.0%
CountingSortBenchmark.Array_Pairs(ItemCount: 1000000) 50.40 ms 295.66 μs 52.78 ms -4.5%
RadixSortBenchmark.Array_Pairs(ItemCount: 1000000) 75.47 ms 1.33 ms 75.18 ms +0.4%
CountingSortBenchmark.CountingSort_Pairs(ItemCount: 1000000) 2.94 ms 42.79 μs 2.91 ms +1.0%
RadixSortBenchmark.RadixSort_Pairs(ItemCount: 1000000) 13.81 ms 270.06 μs 14.02 ms -1.5%
EnumMapBenchmark.Dictionary_Remove 2.03 μs 117.3 ns 2.98 μs -31.8%
EnumMapBenchmark.EnumMap_Remove 1.84 μs 772.4 ns 2.50 μs -26.1%
SmallSetBenchmark.HashSet_Remove(ItemCount: 8) 221.2 ns 56.3 ns 255.9 ns -13.6%
SmallSetBenchmark.SmallSet_Remove(ItemCount: 8) 1.48 μs 846.1 ns 2.30 μs -35.5%
SmallSetBenchmark.HashSet_Remove(ItemCount: 64) 2.35 μs 930.3 ns 1.53 μs +53.8%
SmallSetBenchmark.SmallSet_Remove(ItemCount: 64) 18.55 μs 996.6 ns 21.74 μs -14.6%
CelerityMultiMapBenchmark.Dictionary_Remove(ItemCount: 1000) 20.91 μs 1.44 μs 32.88 μs -36.4% ✅
CelerityMultiMapBenchmark.CelerityMultiMap_Remove(ItemCount: 1000) 89.59 μs 7.99 μs 88.55 μs +1.2%
RobinHoodSetBenchmark.HashSet_Remove(ItemCount: 1000) 31.31 μs 6.81 μs 22.97 μs +36.3%
RobinHoodSetBenchmark.RobinHoodSet_Remove(ItemCount: 1000) 82.54 μs 8.85 μs 91.59 μs -9.9%
CelerityMultiMapBenchmark.Dictionary_Remove(ItemCount: 100000) 1.64 ms 73.75 μs 1.67 ms -2.0%
CelerityMultiMapBenchmark.CelerityMultiMap_Remove(ItemCount: 100000) 1.59 ms 53.01 μs 1.62 ms -2.0%
RobinHoodSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.44 ms 70.09 μs 1.53 ms -5.9%
RobinHoodSetBenchmark.RobinHoodSet_Remove(ItemCount: 100000) 1.33 ms 39.16 μs 1.34 ms -0.2%
TopKSketchBenchmark.Dictionary_TopK(ItemCount: 1000) 31.1 ns 1.7 ns 28.0 ns +11.3% ⚠️
TopKSketchBenchmark.TopKSketch_TopK(ItemCount: 1000) 1.06 μs 47.2 ns 983.6 ns +8.0%
TopKSketchBenchmark.Dictionary_TopK(ItemCount: 100000) 32.4 ns 1.5 ns 29.8 ns +8.7%
TopKSketchBenchmark.TopKSketch_TopK(ItemCount: 100000) 906.0 ns 30.4 ns 944.5 ns -4.1%
BTreeSetBenchmark.SortedSet_Add(ItemCount: 1000) 41.76 μs 464.1 ns 43.23 μs -3.4%
PooledCeleritySetBenchmark.HashSet_Add(ItemCount: 1000) 12.48 μs 143.1 ns 13.41 μs -6.9%
BTreeSetBenchmark.BTreeSet_Add(ItemCount: 1000) 41.25 μs 645.5 ns 41.67 μs -1.0%
PooledCeleritySetBenchmark.PooledCeleritySet_Add(ItemCount: 1000) 9.28 μs 150.7 ns 8.75 μs +6.1%
BTreeSetBenchmark.SortedSet_Add(ItemCount: 100000) 22.30 ms 133.00 μs 22.73 ms -1.9%
PooledCeleritySetBenchmark.HashSet_Add(ItemCount: 100000) 5.03 ms 46.28 μs 5.06 ms -0.7%
BTreeSetBenchmark.BTreeSet_Add(ItemCount: 100000) 15.73 ms 284.88 μs 15.54 ms +1.2%
PooledCeleritySetBenchmark.PooledCeleritySet_Add(ItemCount: 100000) 3.19 ms 5.63 μs 3.18 ms +0.3%
RankSelectBitVectorBenchmark.Array_Build(ItemCount: 1024) 82.9 ns 0.2 ns 82.6 ns +0.5%
RankSelectBitVectorBenchmark.RankSelectBitVector_Build(ItemCount: 1024) 57.9 ns 1.2 ns 59.2 ns -2.1%
RankSelectBitVectorBenchmark.Array_Build(ItemCount: 1000000) 78.60 μs 824.4 ns 77.91 μs +0.9%
RankSelectBitVectorBenchmark.RankSelectBitVector_Build(ItemCount: 1000000) 97.52 μs 516.9 ns 98.10 μs -0.6%
BTreeSetBenchmark.SortedSet_Contains(ItemCount: 1000) 18.92 μs 130.1 ns 18.94 μs -0.1%
PooledCeleritySetBenchmark.HashSet_Contains(ItemCount: 1000) 4.71 μs 2.9 ns 4.69 μs +0.4%
BTreeSetBenchmark.BTreeSet_Contains(ItemCount: 1000) 16.57 μs 104.0 ns 16.54 μs +0.2%
PooledCeleritySetBenchmark.PooledCeleritySet_Contains(ItemCount: 1000) 2.07 μs 56.4 ns 2.02 μs +2.6%
BTreeSetBenchmark.SortedSet_Contains(ItemCount: 100000) 16.37 ms 808.05 μs 16.44 ms -0.4%
PooledCeleritySetBenchmark.HashSet_Contains(ItemCount: 100000) 1.54 ms 20.96 μs 1.52 ms +1.2%
BTreeSetBenchmark.BTreeSet_Contains(ItemCount: 100000) 14.06 ms 21.93 μs 14.09 ms -0.2%
PooledCeleritySetBenchmark.PooledCeleritySet_Contains(ItemCount: 100000) 534.82 μs 21.22 μs 531.87 μs +0.6%
IndexedPriorityQueueBenchmark.PriorityQueue_DecreaseKey(ItemCount: 1000) 76.60 μs 431.7 ns 77.37 μs -1.0%
IndexedPriorityQueueBenchmark.IndexedPriorityQueue_DecreaseKey(ItemCount: 1000) 187.91 μs 272.9 ns 189.36 μs -0.8%
IndexedPriorityQueueBenchmark.PriorityQueue_DecreaseKey(ItemCount: 100000) 34.74 ms 700.47 μs 35.65 ms -2.6%
IndexedPriorityQueueBenchmark.IndexedPriorityQueue_DecreaseKey(ItemCount: 100000) 56.41 ms 308.37 μs 58.14 ms -3.0%
IndexedPriorityQueueBenchmark.PriorityQueue_Enqueue(ItemCount: 1000) 4.59 μs 38.6 ns 4.81 μs -4.7%
IndexedPriorityQueueBenchmark.IndexedPriorityQueue_Enqueue(ItemCount: 1000) 29.51 μs 80.7 ns 29.68 μs -0.5%
IndexedPriorityQueueBenchmark.PriorityQueue_Enqueue(ItemCount: 100000) 1.17 ms 15.00 μs 1.17 ms +0.5%
IndexedPriorityQueueBenchmark.IndexedPriorityQueue_Enqueue(ItemCount: 100000) 6.29 ms 59.72 μs 6.58 ms -4.4%
DequeBenchmark.LinkedList_Enumerate(ItemCount: 1000) 1.66 μs 1.9 ns 1.66 μs +0.1%
DequeBenchmark.Deque_Enumerate(ItemCount: 1000) 1.06 μs 0.8 ns 1.06 μs -0.0%
DequeBenchmark.LinkedList_Enumerate(ItemCount: 100000) 152.07 μs 61.1 ns 152.36 μs -0.2%
DequeBenchmark.Deque_Enumerate(ItemCount: 100000) 105.73 μs 106.1 ns 105.67 μs +0.1%
CelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.06 μs 36.8 ns 13.03 μs +0.2%
IntDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.01 μs 41.8 ns 13.44 μs -3.1%
CelerityDictionaryBenchmark.CelerityDictionary_Insert(ItemCount: 1000) 8.78 μs 254.1 ns 9.07 μs -3.3%
IntDictionaryBenchmark.IntDictionary_Insert(ItemCount: 1000) 8.84 μs 224.3 ns 8.76 μs +1.0%
CelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 4.26 ms 48.56 μs 4.38 ms -2.8%
IntDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 4.24 ms 58.40 μs 4.36 ms -2.6%
CelerityDictionaryBenchmark.CelerityDictionary_Insert(ItemCount: 100000) 5.15 ms 104.52 μs 5.25 ms -2.0%
IntDictionaryBenchmark.IntDictionary_Insert(ItemCount: 100000) 5.13 ms 44.42 μs 5.08 ms +0.9%
CelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.95 μs 361.9 ns 5.12 μs -3.3%
IntDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.60 μs 4.6 ns 4.61 μs -0.1%
CelerityDictionaryBenchmark.CelerityDictionary_Lookup(ItemCount: 1000) 2.40 μs 13.6 ns 2.38 μs +0.9%
IntDictionaryBenchmark.IntDictionary_Lookup(ItemCount: 1000) 2.09 μs 17.4 ns 2.08 μs +0.6%
CelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.60 ms 10.27 μs 1.60 ms -0.0%
IntDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.57 ms 3.20 μs 1.57 ms +0.0%
CelerityDictionaryBenchmark.CelerityDictionary_Lookup(ItemCount: 100000) 707.97 μs 17.66 μs 704.87 μs +0.4%
IntDictionaryBenchmark.IntDictionary_Lookup(ItemCount: 100000) 585.56 μs 9.59 μs 626.22 μs -6.5%
BTreeSetBenchmark.SortedSet_Mixed(ItemCount: 1000) 58.38 μs 1.05 μs 59.38 μs -1.7%
BTreeSetBenchmark.BTreeSet_Mixed(ItemCount: 1000) 54.78 μs 439.2 ns 54.38 μs +0.7%
BTreeSetBenchmark.SortedSet_Mixed(ItemCount: 100000) 33.82 ms 293.28 μs 34.18 ms -1.1%
BTreeSetBenchmark.BTreeSet_Mixed(ItemCount: 100000) 26.15 ms 215.83 μs 26.04 ms +0.4%
DequeBenchmark.LinkedList_PushFront(ItemCount: 1000) 38.44 μs 1.33 μs 36.04 μs +6.7%
DequeBenchmark.Deque_PushFront(ItemCount: 1000) 19.01 μs 1.23 μs 21.82 μs -12.9%
DequeBenchmark.LinkedList_PushFront(ItemCount: 100000) 1.80 ms 65.56 μs 1.81 ms -0.4%
DequeBenchmark.Deque_PushFront(ItemCount: 100000) 762.38 μs 146.98 μs 782.14 μs -2.5%
DequeBenchmark.LinkedList_Queue(ItemCount: 1000) 52.74 μs 4.77 μs 51.20 μs +3.0%
DequeBenchmark.Deque_Queue(ItemCount: 1000) 30.37 μs 3.38 μs 30.15 μs +0.7%
DequeBenchmark.LinkedList_Queue(ItemCount: 100000) 5.27 ms 635.82 μs 4.77 ms +10.4%
DequeBenchmark.Deque_Queue(ItemCount: 100000) 511.12 μs 82.16 μs 458.71 μs +11.4%
BTreeSetBenchmark.SortedSet_RangeScan(ItemCount: 1000) 180.6 ns 1.0 ns 175.0 ns +3.2%
BTreeSetBenchmark.BTreeSet_RangeScan(ItemCount: 1000) 82.2 ns 2.0 ns 79.9 ns +2.9%
BTreeSetBenchmark.SortedSet_RangeScan(ItemCount: 100000) 9.52 μs 145.2 ns 10.07 μs -5.5%
BTreeSetBenchmark.BTreeSet_RangeScan(ItemCount: 100000) 4.97 μs 36.9 ns 4.93 μs +0.7%
RankSelectBitVectorBenchmark.Array_RankEarly(ItemCount: 1024) 1.33 μs 2.3 ns 1.33 μs +0.1%
RankSelectBitVectorBenchmark.RankSelectBitVector_RankEarly(ItemCount: 1024) 2.02 μs 2.1 ns 2.02 μs +0.0%
RankSelectBitVectorBenchmark.Array_RankEarly(ItemCount: 1000000) 30.60 μs 81.8 ns 30.55 μs +0.2%
RankSelectBitVectorBenchmark.RankSelectBitVector_RankEarly(ItemCount: 1000000) 2.02 μs 1.5 ns 2.02 μs +0.1%
RankSelectBitVectorBenchmark.Array_RankLate(ItemCount: 1024) 8.16 μs 8.1 ns 8.16 μs +0.0%
RankSelectBitVectorBenchmark.RankSelectBitVector_RankLate(ItemCount: 1024) 2.02 μs 4.0 ns 2.02 μs +0.1%
RankSelectBitVectorBenchmark.Array_RankLate(ItemCount: 1000000) 5.51 ms 5.59 μs 5.51 ms -0.1%
RankSelectBitVectorBenchmark.RankSelectBitVector_RankLate(ItemCount: 1000000) 2.09 μs 75.8 ns 2.02 μs +3.5%
RankSelectBitVectorBenchmark.Array_RankMid(ItemCount: 1024) 4.61 μs 9.9 ns 4.61 μs +0.1%
RankSelectBitVectorBenchmark.RankSelectBitVector_RankMid(ItemCount: 1024) 2.02 μs 2.7 ns 2.02 μs +0.1%
RankSelectBitVectorBenchmark.Array_RankMid(ItemCount: 1000000) 2.81 ms 5.29 μs 2.81 ms +0.0%
RankSelectBitVectorBenchmark.RankSelectBitVector_RankMid(ItemCount: 1000000) 2.02 μs 1.8 ns 2.02 μs +0.0%
BTreeSetBenchmark.SortedSet_Remove(ItemCount: 1000) 600.01 μs 18.92 μs 603.97 μs -0.7%
CelerityDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 78.27 μs 7.34 μs 79.40 μs -1.4%
IntDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 77.73 μs 8.28 μs 78.09 μs -0.5%
PooledCeleritySetBenchmark.HashSet_Remove(ItemCount: 1000) 28.66 μs 2.68 μs 27.49 μs +4.3%
BTreeSetBenchmark.BTreeSet_Remove(ItemCount: 1000) 254.58 μs 12.57 μs 252.77 μs +0.7%
CelerityDictionaryBenchmark.CelerityDictionary_Remove(ItemCount: 1000) 123.20 μs 6.80 μs 128.22 μs -3.9%
IntDictionaryBenchmark.IntDictionary_Remove(ItemCount: 1000) 89.03 μs 7.33 μs 88.06 μs +1.1%
PooledCeleritySetBenchmark.PooledCeleritySet_Remove(ItemCount: 1000) 118.18 μs 7.51 μs 118.28 μs -0.1%
BTreeSetBenchmark.SortedSet_Remove(ItemCount: 100000) 26.33 ms 132.95 μs 26.30 ms +0.1%
CelerityDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 1.99 ms 15.07 μs 2.02 ms -1.3%
IntDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.01 ms 16.33 μs 2.03 ms -1.2%
PooledCeleritySetBenchmark.HashSet_Remove(ItemCount: 100000) 1.68 ms 14.54 μs 1.68 ms -0.2%
BTreeSetBenchmark.BTreeSet_Remove(ItemCount: 100000) 16.39 ms 35.65 μs 16.38 ms +0.0%
CelerityDictionaryBenchmark.CelerityDictionary_Remove(ItemCount: 100000) 1.69 ms 28.87 μs 1.71 ms -0.8%
IntDictionaryBenchmark.IntDictionary_Remove(ItemCount: 100000) 1.70 ms 40.57 μs 2.62 ms -35.0%
PooledCeleritySetBenchmark.PooledCeleritySet_Remove(ItemCount: 100000) 1.44 ms 16.63 μs 1.44 ms -0.1%
RankSelectBitVectorBenchmark.Array_Select(ItemCount: 1024) 14.05 μs 120.5 ns 14.01 μs +0.2%
RankSelectBitVectorBenchmark.RankSelectBitVector_Select(ItemCount: 1024) 10.41 μs 38.4 ns 10.42 μs -0.2%
RankSelectBitVectorBenchmark.Array_Select(ItemCount: 1000000) 4.78 ms 2.93 μs 4.78 ms +0.0%
RankSelectBitVectorBenchmark.RankSelectBitVector_Select(ItemCount: 1000000) 26.05 μs 22.5 ns 25.90 μs +0.6%
TrieBenchmark.Dictionary_Add(ItemCount: 1000) 38.79 μs 6.31 μs 39.13 μs -0.9%
TrieBenchmark.Trie_Add(ItemCount: 1000) 515.33 μs 15.80 μs 498.43 μs +3.4%
BTreeDictionaryBenchmark.SortedDictionary_Add(ItemCount: 1000) 51.60 μs 4.00 μs 55.36 μs -6.8%
IntSetBenchmark.HashSet_Add(ItemCount: 1000) 13.48 μs 235.6 ns 12.44 μs +8.3%
SwissSetBenchmark.HashSet_Add(ItemCount: 1000) 12.41 μs 180.0 ns 13.23 μs -6.2%
BTreeDictionaryBenchmark.BTreeDictionary_Add(ItemCount: 1000) 54.39 μs 706.0 ns 54.66 μs -0.5%
IntSetBenchmark.IntSet_Add(ItemCount: 1000) 9.73 μs 113.8 ns 9.42 μs +3.3%
SwissSetBenchmark.SwissSet_Add(ItemCount: 1000) 25.60 μs 31.1 ns 26.01 μs -1.6%
TrieBenchmark.Dictionary_Add(ItemCount: 100000) 5.26 ms 1.44 ms 5.52 ms -4.6%
TrieBenchmark.Trie_Add(ItemCount: 100000) 28.99 ms 550.86 μs 29.64 ms -2.2%
BTreeDictionaryBenchmark.SortedDictionary_Add(ItemCount: 100000) 26.33 ms 377.81 μs 25.57 ms +3.0%
IntSetBenchmark.HashSet_Add(ItemCount: 100000) 5.21 ms 92.08 μs 5.25 ms -0.8%
SwissSetBenchmark.HashSet_Add(ItemCount: 100000) 4.98 ms 80.02 μs 5.00 ms -0.3%
BTreeDictionaryBenchmark.BTreeDictionary_Add(ItemCount: 100000) 17.48 ms 93.77 μs 17.31 ms +1.0%
IntSetBenchmark.IntSet_Add(ItemCount: 100000) 3.52 ms 30.93 μs 3.50 ms +0.4%
SwissSetBenchmark.SwissSet_Add(ItemCount: 100000) 4.47 ms 119.19 μs 4.47 ms -0.1%
DisjointSetBenchmark.Dictionary_Components(ItemCount: 1000) 17.83 μs 277.2 ns 17.74 μs +0.5%
DisjointSetBenchmark.DisjointSet_Components(ItemCount: 1000) 15.94 μs 286.4 ns 16.46 μs -3.1%
DisjointSetBenchmark.Dictionary_Components(ItemCount: 100000) 4.46 ms 46.79 μs 4.53 ms -1.5%
DisjointSetBenchmark.DisjointSet_Components(ItemCount: 100000) 3.26 ms 37.03 μs 3.23 ms +0.7%
DisjointSetBenchmark.Dictionary_Connected(ItemCount: 1000) 9.51 μs 4.0 ns 9.54 μs -0.3%
DisjointSetBenchmark.DisjointSet_Connected(ItemCount: 1000) 13.05 μs 17.2 ns 13.02 μs +0.2%
DisjointSetBenchmark.Dictionary_Connected(ItemCount: 100000) 159.01 μs 1.72 μs 156.24 μs +1.8%
DisjointSetBenchmark.DisjointSet_Connected(ItemCount: 100000) 284.67 μs 1.26 μs 284.66 μs +0.0%
IntSetBenchmark.HashSet_Contains(ItemCount: 1000) 5.00 μs 316.8 ns 4.71 μs +6.0%
SwissSetBenchmark.HashSet_Contains(ItemCount: 1000) 4.75 μs 7.1 ns 4.74 μs +0.3%
IntSetBenchmark.IntSet_Contains(ItemCount: 1000) 1.91 μs 21.1 ns 1.92 μs -0.2%
SwissSetBenchmark.SwissSet_Contains(ItemCount: 1000) 2.74 μs 4.8 ns 2.74 μs +0.0%
IntSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.51 ms 5.16 μs 1.54 ms -1.7%
SwissSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.51 ms 2.79 μs 1.55 ms -2.3%
IntSetBenchmark.IntSet_Contains(ItemCount: 100000) 488.01 μs 5.83 μs 506.74 μs -3.7%
SwissSetBenchmark.SwissSet_Contains(ItemCount: 100000) 441.14 μs 30.07 μs 479.69 μs -8.0%
SwissSetBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.57 μs 2.6 ns 4.57 μs -0.1%
SwissSetBenchmark.SwissSet_ContainsMissing(ItemCount: 1000) 2.51 μs 1.5 ns 2.51 μs +0.0%
SwissSetBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 1.99 ms 1.87 μs 1.98 ms +0.7%
SwissSetBenchmark.SwissSet_ContainsMissing(ItemCount: 100000) 316.77 μs 853.4 ns 316.52 μs +0.1%
StringInternTableBenchmark.Dictionary_Dedupe(ItemCount: 1000) 33.56 μs 93.4 ns 33.88 μs -1.0%
StringInternTableBenchmark.StringInternTable_Dedupe(ItemCount: 1000) 37.45 μs 89.0 ns 37.44 μs +0.0%
StringInternTableBenchmark.Dictionary_Dedupe(ItemCount: 100000) 3.33 ms 84.34 μs 3.23 ms +3.2%
StringInternTableBenchmark.StringInternTable_Dedupe(ItemCount: 100000) 3.40 ms 5.12 μs 3.40 ms +0.0%
LongDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 16.25 μs 169.3 ns 15.14 μs +7.4%
LongDictionaryBenchmark.LongDictionary_Insert(ItemCount: 1000) 9.09 μs 100.8 ns 8.67 μs +4.9%
LongDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 5.32 ms 58.06 μs 5.24 ms +1.5%
LongDictionaryBenchmark.LongDictionary_Insert(ItemCount: 100000) 7.81 ms 91.41 μs 7.52 ms +3.9%
BTreeDictionaryBenchmark.SortedDictionary_Lookup(ItemCount: 1000) 24.93 μs 147.7 ns 24.92 μs +0.0%
LongDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 5.03 μs 39.5 ns 5.02 μs +0.2%
StringInternTableBenchmark.HashSet_Lookup(ItemCount: 1000) 31.71 μs 183.4 ns 31.50 μs +0.7%
TrieBenchmark.Dictionary_Lookup(ItemCount: 1000) 12.59 μs 34.0 ns 12.64 μs -0.4%
BTreeDictionaryBenchmark.BTreeDictionary_Lookup(ItemCount: 1000) 19.80 μs 443.9 ns 20.22 μs -2.0%
LongDictionaryBenchmark.LongDictionary_Lookup(ItemCount: 1000) 7.38 μs 5.39 μs 2.29 μs +222.5%
StringInternTableBenchmark.StringInternTable_Lookup(ItemCount: 1000) 33.18 μs 107.6 ns 33.10 μs +0.2%
TrieBenchmark.Trie_Lookup(ItemCount: 1000) 45.47 μs 15.8 ns 45.31 μs +0.3%
BTreeDictionaryBenchmark.SortedDictionary_Lookup(ItemCount: 100000) 19.01 ms 164.38 μs 18.59 ms +2.3%
LongDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.60 ms 21.28 μs 1.57 ms +1.5%
StringInternTableBenchmark.HashSet_Lookup(ItemCount: 100000) 3.17 ms 9.54 μs 3.46 ms -8.3%
TrieBenchmark.Dictionary_Lookup(ItemCount: 100000) 2.78 ms 5.77 μs 2.79 ms -0.3%
BTreeDictionaryBenchmark.BTreeDictionary_Lookup(ItemCount: 100000) 14.19 ms 121.83 μs 14.24 ms -0.4%
LongDictionaryBenchmark.LongDictionary_Lookup(ItemCount: 100000) 704.56 μs 4.68 μs 683.00 μs +3.2%
StringInternTableBenchmark.StringInternTable_Lookup(ItemCount: 100000) 3.38 ms 55.46 μs 3.32 ms +1.8%
TrieBenchmark.Trie_Lookup(ItemCount: 100000) 9.76 ms 193.52 μs 10.27 ms -5.0%
BTreeDictionaryBenchmark.SortedDictionary_Mixed(ItemCount: 1000) 97.96 μs 1.04 μs 91.95 μs +6.5%
BTreeDictionaryBenchmark.BTreeDictionary_Mixed(ItemCount: 1000) 71.32 μs 654.7 ns 71.91 μs -0.8%
BTreeDictionaryBenchmark.SortedDictionary_Mixed(ItemCount: 100000) 50.84 ms 238.31 μs 51.30 ms -0.9%
BTreeDictionaryBenchmark.BTreeDictionary_Mixed(ItemCount: 100000) 27.79 ms 49.33 μs 28.15 ms -1.3%
TrieBenchmark.Dictionary_PrefixMatch(ItemCount: 1000) 79.94 μs 75.5 ns 79.99 μs -0.1%
TrieBenchmark.Trie_PrefixMatch(ItemCount: 1000) 57.52 μs 957.6 ns 56.67 μs +1.5%
TrieBenchmark.Dictionary_PrefixMatch(ItemCount: 100000) 8.07 ms 7.58 μs 8.09 ms -0.2%
TrieBenchmark.Trie_PrefixMatch(ItemCount: 100000) 8.33 ms 1.17 ms 6.12 ms +36.2% ⚠️
BTreeDictionaryBenchmark.SortedDictionary_RangeScan(ItemCount: 1000) 4.57 μs 26.1 ns 4.62 μs -1.2%
BTreeDictionaryBenchmark.BTreeDictionary_RangeScan(ItemCount: 1000) 81.4 ns 1.2 ns 80.9 ns +0.7%
BTreeDictionaryBenchmark.SortedDictionary_RangeScan(ItemCount: 100000) 1.18 ms 5.03 μs 1.19 ms -1.1%
BTreeDictionaryBenchmark.BTreeDictionary_RangeScan(ItemCount: 100000) 5.80 μs 16.0 ns 5.80 μs +0.1%
BTreeDictionaryBenchmark.SortedDictionary_Remove(ItemCount: 1000) 672.01 μs 11.58 μs 687.88 μs -2.3%
IntSetBenchmark.HashSet_Remove(ItemCount: 1000) 27.45 μs 1.89 μs 27.18 μs +1.0%
LongDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 82.23 μs 7.83 μs 85.08 μs -3.3%
BTreeDictionaryBenchmark.BTreeDictionary_Remove(ItemCount: 1000) 285.97 μs 11.85 μs 287.55 μs -0.5%
IntSetBenchmark.IntSet_Remove(ItemCount: 1000) 81.32 μs 7.18 μs 83.16 μs -2.2%
LongDictionaryBenchmark.LongDictionary_Remove(ItemCount: 1000) 90.77 μs 5.37 μs 81.06 μs +12.0%
SwissSetBenchmark.HashSet_Remove(ItemCount: 1000) 26.87 μs 2.59 μs 26.36 μs +1.9%
SwissSetBenchmark.SwissSet_Remove(ItemCount: 1000) 66.17 μs 3.75 μs 65.42 μs +1.1%
BTreeDictionaryBenchmark.SortedDictionary_Remove(ItemCount: 100000) 28.54 ms 854.53 μs 28.58 ms -0.2%
IntSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.70 ms 20.04 μs 1.70 ms -0.2%
LongDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.00 ms 59.73 μs 1.98 ms +0.7%
BTreeDictionaryBenchmark.BTreeDictionary_Remove(ItemCount: 100000) 19.64 ms 60.22 μs 19.45 ms +1.0%
IntSetBenchmark.IntSet_Remove(ItemCount: 100000) 1.42 ms 64.23 μs 1.45 ms -1.6%
LongDictionaryBenchmark.LongDictionary_Remove(ItemCount: 100000) 1.96 ms 205.67 μs 1.79 ms +9.6%
SwissSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.72 ms 20.09 μs 1.70 ms +0.9%
SwissSetBenchmark.SwissSet_Remove(ItemCount: 100000) 865.75 μs 15.47 μs 856.36 μs +1.1%
TrieBenchmark.Dictionary_SpanLookup(ItemCount: 1000) 40.70 μs 579.6 ns 38.22 μs +6.5%
TrieBenchmark.Trie_SpanLookup(ItemCount: 1000) 46.71 μs 60.7 ns 46.38 μs +0.7%
TrieBenchmark.Dictionary_SpanLookup(ItemCount: 100000) 6.55 ms 90.71 μs 6.37 ms +2.9%
TrieBenchmark.Trie_SpanLookup(ItemCount: 100000) 10.91 ms 100.25 μs 9.78 ms +11.6% ⚠️
DisjointSetBenchmark.Dictionary_Union(ItemCount: 1000) 94.47 μs 1.74 μs 94.88 μs -0.4%
DisjointSetBenchmark.DisjointSet_Union(ItemCount: 1000) 27.48 μs 114.6 ns 27.55 μs -0.3%
DisjointSetBenchmark.Dictionary_Union(ItemCount: 100000) 43.36 ms 1.02 ms 46.23 ms -6.2%
DisjointSetBenchmark.DisjointSet_Union(ItemCount: 100000) 7.87 ms 36.48 μs 7.85 ms +0.3%
Hashers (111)
Benchmark This PR StdDev main Δ
StringHasherBenchmark.Bcl_GetHashCode(Shape: ShortAscii) 13.97 μs 28.0 ns 13.95 μs +0.1%
StringHasherBenchmark.EqualityComparer_Default(Shape: ShortAscii) 13.96 μs 14.5 ns 13.95 μs +0.1%
StringHasherBenchmark.Djb2(Shape: ShortAscii) 22.62 μs 153.6 ns 22.58 μs +0.2%
StringHasherBenchmark.Djb2A(Shape: ShortAscii) 22.55 μs 163.5 ns 22.55 μs +0.0%
StringHasherBenchmark.Sdbm(Shape: ShortAscii) 29.36 μs 163.9 ns 29.32 μs +0.1%
StringHasherBenchmark.Elf(Shape: ShortAscii) 73.32 μs 124.4 ns 73.32 μs +0.0%
StringHasherBenchmark.Crc32(Shape: ShortAscii) 45.17 μs 78.1 ns 45.09 μs +0.2%
StringHasherBenchmark.Adler32(Shape: ShortAscii) 83.08 μs 135.7 ns 82.97 μs +0.1%
StringHasherBenchmark.FnV1(Shape: ShortAscii) 19.23 μs 95.2 ns 19.26 μs -0.1%
StringHasherBenchmark.FnV1_64(Shape: ShortAscii) 22.16 μs 53.4 ns 22.17 μs -0.0%
StringHasherBenchmark.FnV1A(Shape: ShortAscii) 18.59 μs 53.0 ns 18.59 μs +0.0%
StringHasherBenchmark.FnV1A_Full(Shape: ShortAscii) 19.60 μs 117.0 ns 19.58 μs +0.1%
StringHasherBenchmark.FnV1A_64(Shape: ShortAscii) 22.77 μs 134.7 ns 22.69 μs +0.3%
StringHasherBenchmark.JenkinsOaat(Shape: ShortAscii) 34.19 μs 137.8 ns 34.18 μs +0.0%
StringHasherBenchmark.Murmur2(Shape: ShortAscii) 12.57 μs 47.6 ns 12.56 μs +0.0%
StringHasherBenchmark.Murmur3(Shape: ShortAscii) 15.59 μs 19.9 ns 15.59 μs -0.0%
StringHasherBenchmark.XxHash32(Shape: ShortAscii) 14.21 μs 25.5 ns 14.21 μs -0.0%
StringHasherBenchmark.XxHash64(Shape: ShortAscii) 16.18 μs 22.8 ns 16.18 μs -0.0%
StringHasherBenchmark.XxHash3(Shape: ShortAscii) 13.56 μs 12.5 ns 13.59 μs -0.2%
StringHasherBenchmark.CityHash64(Shape: ShortAscii) 13.02 μs 19.4 ns 13.05 μs -0.2%
StringHasherBenchmark.MetroHash64(Shape: ShortAscii) 13.91 μs 13.4 ns 13.94 μs -0.2%
StringHasherBenchmark.SipHash13(Shape: ShortAscii) 25.37 μs 37.0 ns 25.36 μs +0.0%
StringHasherBenchmark.SipHash24(Shape: ShortAscii) 36.69 μs 46.1 ns 36.65 μs +0.1%
StringHasherBenchmark.HalfSipHash24(Shape: ShortAscii) 50.98 μs 37.8 ns 50.97 μs +0.0%
StringHasherBenchmark.HighwayHash64(Shape: ShortAscii) 286.00 μs 418.2 ns 285.16 μs +0.3%
StringHasherBenchmark.XxHash64_Hash64(Shape: ShortAscii) 15.61 μs 18.5 ns 15.60 μs +0.1%
StringHasherBenchmark.SipHash24_Hash64(Shape: ShortAscii) 36.25 μs 33.5 ns 36.23 μs +0.1%
StringHasherBenchmark.Bcl_GetHashCode(Shape: LongAscii) 101.72 μs 172.5 ns 102.18 μs -0.4%
StringHasherBenchmark.EqualityComparer_Default(Shape: LongAscii) 102.27 μs 146.1 ns 102.33 μs -0.1%
StringHasherBenchmark.Djb2(Shape: LongAscii) 220.63 μs 820.0 ns 220.67 μs -0.0%
StringHasherBenchmark.Djb2A(Shape: LongAscii) 221.17 μs 852.4 ns 221.00 μs +0.1%
StringHasherBenchmark.Sdbm(Shape: LongAscii) 319.79 μs 152.9 ns 319.96 μs -0.1%
StringHasherBenchmark.Elf(Shape: LongAscii) 713.19 μs 10.87 μs 713.43 μs -0.0%
StringHasherBenchmark.Crc32(Shape: LongAscii) 590.04 μs 7.27 μs 582.72 μs +1.3%
StringHasherBenchmark.Adler32(Shape: LongAscii) 789.97 μs 1.09 μs 790.14 μs -0.0%
StringHasherBenchmark.FnV1(Shape: LongAscii) 236.47 μs 139.9 ns 236.58 μs -0.0%
StringHasherBenchmark.FnV1_64(Shape: LongAscii) 256.61 μs 602.7 ns 256.58 μs +0.0%
StringHasherBenchmark.FnV1A(Shape: LongAscii) 112.16 μs 280.2 ns 112.37 μs -0.2%
StringHasherBenchmark.FnV1A_Full(Shape: LongAscii) 240.10 μs 194.8 ns 240.16 μs -0.0%
StringHasherBenchmark.FnV1A_64(Shape: LongAscii) 262.45 μs 953.5 ns 262.09 μs +0.1%
StringHasherBenchmark.JenkinsOaat(Shape: LongAscii) 382.01 μs 209.1 ns 382.14 μs -0.0%
StringHasherBenchmark.Murmur2(Shape: LongAscii) 99.16 μs 1.30 μs 98.82 μs +0.3%
StringHasherBenchmark.Murmur3(Shape: LongAscii) 115.90 μs 120.5 ns 115.90 μs -0.0%
StringHasherBenchmark.XxHash32(Shape: LongAscii) 74.67 μs 203.1 ns 74.79 μs -0.2%
StringHasherBenchmark.XxHash64(Shape: LongAscii) 75.80 μs 60.1 ns 75.83 μs -0.0%
StringHasherBenchmark.XxHash3(Shape: LongAscii) 67.24 μs 358.9 ns 67.29 μs -0.1%
StringHasherBenchmark.CityHash64(Shape: LongAscii) 107.13 μs 149.5 ns 107.10 μs +0.0%
StringHasherBenchmark.MetroHash64(Shape: LongAscii) 71.74 μs 59.7 ns 71.82 μs -0.1%
StringHasherBenchmark.SipHash13(Shape: LongAscii) 106.25 μs 82.4 ns 106.30 μs -0.0%
StringHasherBenchmark.SipHash24(Shape: LongAscii) 143.82 μs 162.9 ns 144.01 μs -0.1%
StringHasherBenchmark.HalfSipHash24(Shape: LongAscii) 261.47 μs 250.0 ns 261.70 μs -0.1%
StringHasherBenchmark.HighwayHash64(Shape: LongAscii) 446.38 μs 505.2 ns 479.65 μs -6.9%
StringHasherBenchmark.XxHash64_Hash64(Shape: LongAscii) 74.48 μs 91.9 ns 74.48 μs -0.0%
StringHasherBenchmark.SipHash24_Hash64(Shape: LongAscii) 143.76 μs 175.1 ns 143.80 μs -0.0%
StringHasherBenchmark.Bcl_GetHashCode(Shape: NonAscii) 21.46 μs 37.8 ns 21.44 μs +0.1%
StringHasherBenchmark.EqualityComparer_Default(Shape: NonAscii) 21.39 μs 34.3 ns 21.39 μs +0.0%
StringHasherBenchmark.Djb2(Shape: NonAscii) 39.16 μs 193.6 ns 39.00 μs +0.4%
StringHasherBenchmark.Djb2A(Shape: NonAscii) 38.99 μs 264.1 ns 38.92 μs +0.2%
StringHasherBenchmark.Sdbm(Shape: NonAscii) 57.46 μs 139.2 ns 57.36 μs +0.2%
StringHasherBenchmark.Elf(Shape: NonAscii) 124.43 μs 1.30 μs 124.25 μs +0.1%
StringHasherBenchmark.Crc32(Shape: NonAscii) 91.98 μs 240.9 ns 91.77 μs +0.2%
StringHasherBenchmark.Adler32(Shape: NonAscii) 157.24 μs 262.1 ns 156.78 μs +0.3%
StringHasherBenchmark.FnV1(Shape: NonAscii) 40.36 μs 221.8 ns 40.22 μs +0.3%
StringHasherBenchmark.FnV1_64(Shape: NonAscii) 45.13 μs 128.4 ns 45.10 μs +0.1%
StringHasherBenchmark.FnV1A(Shape: NonAscii) 24.91 μs 563.3 ns 24.32 μs +2.4%
StringHasherBenchmark.FnV1A_Full(Shape: NonAscii) 40.71 μs 113.2 ns 40.62 μs +0.2%
StringHasherBenchmark.FnV1A_64(Shape: NonAscii) 42.59 μs 133.3 ns 42.35 μs +0.6%
StringHasherBenchmark.JenkinsOaat(Shape: NonAscii) 68.32 μs 153.0 ns 68.10 μs +0.3%
StringHasherBenchmark.Murmur2(Shape: NonAscii) 30.42 μs 75.4 ns 30.36 μs +0.2%
StringHasherBenchmark.Murmur3(Shape: NonAscii) 25.62 μs 263.4 ns 25.64 μs -0.1%
StringHasherBenchmark.XxHash32(Shape: NonAscii) 20.81 μs 63.0 ns 20.79 μs +0.1%
StringHasherBenchmark.XxHash64(Shape: NonAscii) 26.44 μs 28.6 ns 26.40 μs +0.1%
StringHasherBenchmark.XxHash3(Shape: NonAscii) 20.90 μs 56.1 ns 20.80 μs +0.5%
StringHasherBenchmark.CityHash64(Shape: NonAscii) 20.47 μs 38.1 ns 20.45 μs +0.1%
StringHasherBenchmark.MetroHash64(Shape: NonAscii) 23.81 μs 15.7 ns 23.82 μs -0.0%
StringHasherBenchmark.SipHash13(Shape: NonAscii) 32.31 μs 35.2 ns 32.29 μs +0.1%
StringHasherBenchmark.SipHash24(Shape: NonAscii) 48.37 μs 41.2 ns 48.37 μs -0.0%
StringHasherBenchmark.HalfSipHash24(Shape: NonAscii) 73.69 μs 51.2 ns 73.72 μs -0.0%
StringHasherBenchmark.HighwayHash64(Shape: NonAscii) 296.96 μs 288.5 ns 297.05 μs -0.0%
StringHasherBenchmark.XxHash64_Hash64(Shape: NonAscii) 25.59 μs 22.8 ns 25.60 μs -0.0%
StringHasherBenchmark.SipHash24_Hash64(Shape: NonAscii) 47.69 μs 36.4 ns 47.69 μs +0.0%
IntegerHasherBenchmark.Guid_Bcl 1.27 μs 4.1 ns 1.27 μs +0.1%
IntegerHasherBenchmark.Guid_EqualityComparer 3.49 μs 16.8 ns 3.50 μs -0.4%
IntegerHasherBenchmark.Guid_Celerity 8.49 μs 26.9 ns 8.50 μs -0.1%
IntegerHasherBenchmark.Guid_Celerity_Hash64 8.02 μs 9.0 ns 8.02 μs +0.0%
IntegerHasherBenchmark.Int32_Bcl 686.0 ns 1.1 ns 685.3 ns +0.1%
IntegerHasherBenchmark.Int32_EqualityComparer 703.4 ns 5.5 ns 698.8 ns +0.7%
IntegerHasherBenchmark.Int32_Identity 688.6 ns 8.5 ns 683.8 ns +0.7%
IntegerHasherBenchmark.Int32_WangNaive 1.25 μs 0.6 ns 1.25 μs -0.0%
IntegerHasherBenchmark.Int32_Wang 3.02 μs 2.0 ns 3.02 μs +0.0%
IntegerHasherBenchmark.Int32_Murmur3 2.64 μs 2.6 ns 2.65 μs -0.1%
IntegerHasherBenchmark.Int64_Bcl 1.27 μs 0.8 ns 1.26 μs +0.5%
IntegerHasherBenchmark.Int64_EqualityComparer 1.25 μs 0.4 ns 1.25 μs +0.0%
IntegerHasherBenchmark.Int64_Identity 684.4 ns 1.2 ns 684.3 ns +0.0%
IntegerHasherBenchmark.Int64_WangNaive 1.87 μs 1.2 ns 1.87 μs +0.1%
IntegerHasherBenchmark.Int64_Wang 4.16 μs 4.1 ns 4.16 μs -0.0%
IntegerHasherBenchmark.Int64_Murmur3 2.37 μs 1.5 ns 2.37 μs -0.0%
IntegerHasherBenchmark.Int64_Wang_Hash64 4.16 μs 2.7 ns 4.16 μs +0.0%
IntegerHasherBenchmark.Int64_Murmur3_Hash64 2.37 μs 2.5 ns 2.37 μs +0.1%
IntegerHasherBenchmark.UInt32_Bcl 690.1 ns 8.2 ns 690.0 ns +0.0%
IntegerHasherBenchmark.UInt32_EqualityComparer 702.2 ns 5.6 ns 692.4 ns +1.4%
IntegerHasherBenchmark.UInt32_Default 1.25 μs 0.3 ns 1.25 μs +0.0%
IntegerHasherBenchmark.UInt32_Wang 3.02 μs 3.3 ns 3.02 μs +0.0%
IntegerHasherBenchmark.UInt32_Murmur3 2.65 μs 2.2 ns 2.65 μs +0.0%
IntegerHasherBenchmark.UInt64_Bcl 1.27 μs 0.9 ns 1.27 μs +0.0%
IntegerHasherBenchmark.UInt64_EqualityComparer 1.25 μs 0.5 ns 1.25 μs +0.0%
IntegerHasherBenchmark.UInt64_Default 2.37 μs 2.2 ns 2.37 μs -0.0%
IntegerHasherBenchmark.UInt64_Wang 4.16 μs 2.2 ns 4.16 μs -0.0%
IntegerHasherBenchmark.UInt64_WangNaive 1.87 μs 1.0 ns 1.87 μs -0.0%
IntegerHasherBenchmark.UInt64_Default_Hash64 2.37 μs 1.1 ns 2.37 μs -0.0%
IntegerHasherBenchmark.UInt64_Wang_Hash64 4.16 μs 2.8 ns 4.16 μs +0.0%

Same-runner A/B (sharded 8-way): main (89026ce) and this PR were built and benchmarked back-to-back on the same runner per shard, so hardware variance cancels out. ⚠️ = PR mean ≥ +10% slower than main and beyond combined std-dev; ✅ = correspondingly faster.

@marius-bughiu

Copy link
Copy Markdown
Owner Author

Full run green — all 21 checks, including all 8 benchmark shards

The f06f4b1 run completed successfully end to end, so every claim in this PR is now measured rather than argued.

The base step measures a slice again, not the suite. Shard 6, head against base on the same runner:

head:  Global total time: 00:45:43, executed benchmarks: 96
base:  Global total time: 00:46:33, executed benchmarks: 96

Same count, same duration. On the previous run the base was 53 minutes into the whole suite when the job was killed.

The timeout raise was necessary, not cosmetic. Final job durations against the old 120-minute cap:

shard 0 5 3 2 1 7 4 6
minutes 126.8 124.1 121.1 118.9 106.0 105.9 96.6 93.2

Three shards exceeded 120 minutes and would have been cancelled, with the imbalance already fixed and effectively no competing runs — and shard 2 cleared it by 1.1 minutes, which is not a margin. The heaviest is 126.8 min against the new 180-minute budget, leaving ~30% headroom.

Everything else validated live during the review loop:

One thing for you rather than for this PR

The comparison comment on this PR flags 8 regressions and 5 improvements — on a diff whose library IL is byte-identical to main. The only src/ file here is Celerity.Benchmarks/Program.cs, and that change touches shard selection, never a measured path. Four of the flagged rows are BCL baseline arms (Dictionary_Remove +33.1%, HashSet_Union +24.1%, Dictionary_Lookup -23.5%), where the implementation cannot have changed.

The cause looks structural rather than incidental: the guard compares a between-run mean shift against BenchmarkDotNet's StandardDeviation, which is within-run iteration spread. A row with tight intra-run dispersion and a shifted mean clears it every time.

I have not touched it here — it is a separate change to the reporting half, and this PR is already three issues wide. Filed as #351 with the numbers and five approaches. Please read this PR's own benchmark comment as noise.

Nothing outstanding from the review loop: four Copilot rounds, four findings, all fixed and answered, no threads left open.

@marius-bughiu
marius-bughiu merged commit 04020bf into main Aug 7, 2026
22 checks passed
@marius-bughiu
marius-bughiu deleted the fix/issue-335-benchmark-ci-integrity branch August 7, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants